單例模式的三種實現方式
阿新 • • 發佈:2018-07-02
let ini dict 重新 文件中 rap acl return **kwargs
一、單例模式的三種實現方式
1. 什麽是單例模式
- 基於某種方法,實例化多次,得到同一個實例/對象
2. 為什麽用單例模式
- 實例化多次,得到的對象屬性內容都一樣時,應該將這些對象指向同一個內存,即同一個實例,來節省內存空間
1. 實現單例模式方式一:類內部定義類方法實現
- 實現方法:類中定義了一個類方法
# 未單例模式前 import setting class Mysql: def __init__(self,ip,port): self.ip=ip self.port=port @classmethod def from_conf(cls): return cls(setting.IP,setting.PORT) obj1=Mysql.from_conf() obj2=Mysql.from_conf() obj3=Mysql.from_conf() # 內容相同 print(obj1.__dict__) print(obj2.__dict__) print(obj3.__dict__) # 但是占用不同的內存空間,導致內存空間浪費 print(obj1) print(obj2) print(obj3) ---------------------------------------------------- {‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306} {‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306} {‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306} <__main__.Mysql object at 0x000001B0F234F588> <__main__.Mysql object at 0x000001B0F234F5F8> <__main__.Mysql object at 0x000001B0F234F630>
# setting配置文件 IP=‘10.0.0.1‘ PORT=3306 import setting class Mysql: # 先定義一個變量,用於接收對象 __instance=None def __init__(self,ip,port): self.ip=ip self.port=port @classmethod def from_conf(cls): # 如果沒有實例化過,就重新實例化,如果有就返回實例化過的對象 if cls.__instance is None: cls.__instance=cls(setting.IP,setting.PORT) return cls.__instance obj1=Mysql.from_conf() obj2=Mysql.from_conf() obj3=Mysql.from_conf() # 內容相同 print(obj1.__dict__) print(obj2.__dict__) print(obj3.__dict__) # 占用相同的內存空間 print(obj1) print(obj2) print(obj3) --------------------------------------------------------------- {‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306} {‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306} {‘ip‘: ‘10.0.0.1‘, ‘port‘: 3306} <__main__.Mysql object at 0x000001A79D29F588> <__main__.Mysql object at 0x000001A79D29F588> <__main__.Mysql object at 0x000001A79D29F588> # 如果ip,port不同,再單獨造對象 obj4=Mysql(‘10.0.0.10‘,3307) print(obj4) print(obj4.__dict__) --------------------------------------------------------------- <__main__.Mysql object at 0x0000015D8C13F630> {‘ip‘: ‘10.0.0.10‘, ‘port‘: 3307}
2. 實現單例模式方式二:利用裝飾器實現
_intance
是一種命名習慣,代表在函數內使用的名字
import setting def singleton(cls): _intance=cls(setting.IP,setting.PORT) def wrapper(*args,**kwargs): if len(args) == 0 and len(kwargs) == 0: return _intance return cls(*args,**kwargs) return wrapper @singleton # Mysql=singleton(Mysql) Mysql=wrapper class Mysql: def __init__(self,ip,port): self.ip=ip self.port=port obj1=Mysql() # wrapper() obj2=Mysql() obj3=Mysql() print(obj1 is obj2 is obj3) print(obj1) print(obj2) print(obj3) ----------------------------------------------------- True <__main__.Mysql object at 0x000001ED9FBDF588> <__main__.Mysql object at 0x000001ED9FBDF588> <__main__.Mysql object at 0x000001ED9FBDF588>
3. 實現單例模式方式三:定制元類實現
import setting
class Mymeta(type):
def __init__(self,class_name,class_bases,class_dic): # self=Mysql
super().__init__(class_name,class_bases,class_dic)
# 創造一個Mysql的空對象
self.__instance=self.__new__(self)
# 從配置文件中獲取信息,初始化Mysql的對象
self.__init__(self.__instance,setting.IP,setting.PORT)
def __call__(self, *args, **kwargs): # self=Mysql
if len(args) == 0 and len(kwargs) == 0:
return self.__instance # 返回的是一個已經創建好的Mysql對象
# 如果在Myql()括號內,單獨傳入內容,再重新造對象
obj=self.__new__(self)
self.__init__(self,*args,**kwargs)
return obj
class Mysql(object,metaclass=Mymeta):
def __init__(self,ip,port):
self.ip=ip
self.port=port
obj1=Mysql()
obj2=Mysql()
obj3=Mysql()
obj4=Mysql(‘10.0.0.10‘,3307)
print(obj1)
print(obj2)
print(obj3)
print(obj4)
--------------------------------------------------------------------------
<__main__.Mysql object at 0x0000021DBB7FF668>
<__main__.Mysql object at 0x0000021DBB7FF668>
<__main__.Mysql object at 0x0000021DBB7FF668>
<__main__.Mysql object at 0x0000021DBB7FF6A0>
單例模式的三種實現方式