Python實現Singleton模式


轉載自:https://blog.csdn.net/lqxqust/article/details/51910007

 

Singleton模式即單例對象必須必須保證只有一個實例存在。可以說Singleton是設計模式中最基本一種設計模式,在學習設計模式時一般都會先了解該模式。在Python中實現單例模式有很多方法,下面簡單總結以下,可以根據情況選擇適合自己業務場景的一種進行實現。 
1. 如果在C++中實現過單例模式,在Python中比較常想到的實現方法是借助__new__方法實現:

class Singleton(object): instance = None def __new__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super().__new__(cls, *args, **kwargs) return cls.instance t1 = Singleton() t2 = Singleton() assert id(t1) == id(t2)

該方法基本可以保證只有一個實例,但存在並發的問題。 
2. 在C++中實現Singleton模式的時候也會考慮多線程的問題,在Pyhton中同樣存在該問題,可以通過加鎖進行解決。

import threading class Singleton(object): vars = {} single_lock = threading.Lock() def __new__(cls, *args, **kwargs): if cls in cls.vars: return cls.vars[cls] cls.single_lock.acquire() try: if cls in cls.vars: return cls.vars[cls] cls.vars[cls] = super().__new__(cls, *args, **kwargs) return cls.vars[cls] finally: cls.single_lock.release()

以上兩種都是在類似C++的語言中實現的常用方法,但是在Python中實現不那么Pytonic,並且被子類重載可能還存在問題。 
3. 在《改善Python程序的91個建議》中介紹了一種方法,Python的import機制天然支持單例的實現。 
1. 所有變量都會綁定到模塊 
2. 模式只初始化一次 
3. import機制是線程安全的 
該放很多情況下都可以滿足單例的使用,實現有時覺得有點隱晦。 
4. 有沒有更Pythnic得方法,並且有比較易於使用的呢?大Python當時是無所不能了O(∩_∩)O~,通過使用元類來實現。元類就是用來控制創建類的類。

class SingletonMeta(type): def __init__(cls, name, bases, namespaces): super().__init__(cls, name, bases, namespaces) cls.instance = None def __call__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super().__call__(*args, **kwargs) else: print("instance already existed!") return cls.instance class Singleton(meta=Singleton): pass t1 = Singleton() t2 = Singleton()

實現了__call__方法這個類就成為可調用的,類似於重載了括號操作符,因為在元類中實現__call__,則使用Singleton()實例化類時就會調用__call__,對其進行了單例創建的控制。 
4. 還有一種Pythonic的方法時使用decorator實現

def singleton(cls, *args, **kwargs): instances = {} def wrapper(): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return _wrapper @singleton class Singleton(object): pass t1 = Singleton() t2 = Singleton()

以上是Python中常見的實現單例模式的方法,在實際開發中,可以根據應用場景選擇自己喜歡的方式實現,個人覺得通過元類或裝飾器方式實現還是非常的方便和Pythonic。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM