比如,某個服務器的配置信息存在在一個文件中,客戶端通過AppConfig類來讀取配置文件的信息.
實現單例模式的幾種方法
其實,python的模塊就是天然的單例模式,因爲模塊在第一次導入的時候,會生成.pyc文件,當第二次導入的時候,就會直接加載.pyc文件,而不是再次執行模塊代碼.如果我們把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了.
裝飾器裏面的外層變量定義一個字典,裏面存放這個類的實例.當第一次創建的收,就將這個實例保存到這個字典中.
然後以後每次創建對象的時候,都去這個字典中判斷一下,如果已經被實例化,就直接取這個實例對象.如果不存在就保存到字典中.
def singleton(cls):
# 單下劃線的作用是這個變量只能在當前模塊裏訪問,僅僅是一種提示作用
# 創建一個字典用來保存類的實例對象
_instance = {}
def _singleton(*args, **kwargs):
# 先判斷這個類有沒有對象
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs) # 創建一個對象,並保存到字典當中
# 將實例對象返回
return _instance[cls]
return _singleton
@singleton
class A(object):
a = 1
def __init__(self, x=0):
self.x = x
print('這是A的類的初始化方法')
a1 = A(2)
a2 = A(3)
print(id(a1), id(a2))
3.使用類
思路就是,調用類的instance方法,這樣有一個弊端就是在使用類創建的時候,並不是單例了.也就是說在創建類的時候一定要用類裏面規定的方法創
class Singleton(object):
def __init__(self,*args,**kwargs):
pass
@classmethod
def get_instance(cls, *args, **kwargs):
# 利用反射,看看這個類有沒有_instance屬性
if not hasattr(Singleton, '_instance'):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
s1 = Singleton() # 使用這種方式創建實例的時候,並不能保證單例
s2 = Singleton.get_instance() # 只有使用這種方式創建的時候纔可以實現單例
s3 = Singleton()
s4 = Singleton.get_instance()
print(id(s1), id(s2), id(s3), id(s4))
__new__
方法實現的單例模式(推薦使用,方便)知識點:
1> 一個對象的實例化過程是先執行類的
__new__方法
,如果我們沒有寫,默認會調用object的__new__
方法,返回一個實例化對象,然後再調用__init__方法
,對這個對象進行初始化,我們可以根據這個實現單例.2> 在一個類的
__new__方法中
先判斷是不是存在實例,如果存在實例,就直接返回,如果不存在實例就創建.import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self, *args, **kwargs):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
with Singleton._instance_lock:
if not hasattr(cls, '_instance'):
Singleton._instance = super().__new__(cls)
return Singleton._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1, obj2)
def task(arg):
obj = Singleton()
print(obj)
for i in range(10):
t = threading.Thread(target=task, args=[i, ])
t.start()
參考:https://www.jianshu.com/p/6a1690f0dd00