什麼是單例模式:
單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。
比如,系統的配置信息,在整個項目種很多地方會使用到,但是配置信息是不會在項目種被更改的,如果重複的創建配置信息的對象的化,會嚴重的浪費內存資源,如果能只存在一個對象,那就好了,由此而生的單例模式。
單例模式的創建有以下幾個方式:
1.做成一個模塊。
例:
在一個a.py文件中寫好配置文件的信息的類方法,並給它創建了一個實例對象。再項目中要使用的時候,就直接 from a import singleton 把這個實例對象導進來。
class Singleton(object):
def test(self):
pass
singleton = Singleton()
2.利用裝飾器。
例:
利用了下閉包。 在創建test方法的時候,執行singleton(test)語句。
外層函數調用內層函數,內層函數使用外層函數中的test對象。用一個字典instances 來判斷是否已經創建了實例,若沒有則創建test的實例對象,並把test類 和 test實例對象存到字典中,返回test;若已經創建,則直接返回字典中存儲的test實例對象。(這裏在多線程中出現資源搶奪問題,可以加鎖解決。)
def singleton(cls):
instances = {}
def singleton_in(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return singleton_in
@singleton #這句話就大致可以理解 test()=singleton(test)
class test(object):
pass
a=test()
b=test()
3.重寫類的__new__方法。
例:
new :必須得有一個參數,表示要實例化的類,必須得有返回值,返回值是實例化出來的實例。類被實例化時,是先執行__new__方法,再執行__init__方法,__init__方法中的self是__new__方法中返回的實例對象。
代碼中用__instance的類屬性做控制,這個屬性存儲的是第一次實例化的對象。
裏面有with Singleton.__lock ,上下文資源管理器來給判斷語句加上鎖。這樣就可防止多線程中的資源搶奪的問題,造成創建了多個實例。
class Singleton(object):
__lock = threading.Lock()
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "__instance"):
with Singleton.__lock:
if not hasattr(Singleton, "__instance"):
Singleton.__instance = object.__new__(cls)
return Singleton.__instance
4.利用元類機制(原理和上一種一樣)
metaclass
metaclass=SingletonType這句話的意思是創建Test類用SingletonType方法來創建, 即執行SingletonType() 這個語句,調用__call__方法。
Test創建一個實例對象後,以後再創建時,只是讓變量b指向實例對象的地址,也不會再執行__init__的方法,即b = Test()中 不傳參數也可以執行。
import threading
class SingletonType(type):
__lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "__instance"):
with SingletonType.__lock:
if not hasattr(cls, "__instance"):
cls.__instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls.__instance
class Test(metaclass=SingletonType):
def __init__(self,name):
self.name = name
def single(self,aaa):
print('唱歌',aaa)
def happy(self):
print('唱歌')
a = Test('1111')
b = Test()
a.single('山無棱')
b.single('天地合')
print(id(a))
print(id(b))