設(shè)計模式-單例-Python實現(xiàn)

單例是什么?

單例模式,也叫單子模式,是一種常用的軟件設(shè)計模式。在應(yīng)用這個模式時,單例對象的必須保證只有一個實例存在。許多時候整個系統(tǒng)只需要擁有一個的全局對象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為。

維基百科-單例模式

簡單來說,就是某種類,它有且就有一個實例。

在Python中怎么實現(xiàn)

重寫__new__方法

__new__是類在創(chuàng)建時(不是實例化)時會調(diào)用的成員方法,其參數(shù)是這個類本身,即cls。這里我們使用hasattr方法來判斷一個類有沒有實例。如果沒有就新建一個,有的話就返回當(dāng)前的那個。這樣就保證了這個類永遠(yuǎn)只會有一個實例。

# singleton
class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

class MyClass(Singleton):
    a = 1


A = MyClass()
B = MyClass()

print (A is B)

裝飾器實現(xiàn)

這個方法的核心思想就是將對象的實例用其他的容器保存下來,每次實例類的時候,裝飾器會判斷這個類是不是已經(jīng)在容器中了。如果是,則直接返回容器中的實例,否則則新建一個實例返回并放入容器中。容器中最多只會有一個值。

# singleton
def singleton(cls):
    instances = {}
    def getinstance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return getinstance

@singleton
class MyClass():
    a = 1

A = MyClass()
B = MyClass()

print (A is B)

用list 也可以

# singleton
def singleton(cls):
    instances = []
    def getinstance(*args, **kwargs):
        if not instances:
           instances.append(cls(*args, **kwargs))
        return instances[0]
    return getinstance

@singleton
class MyClass():
    a = 1

A = MyClass()
B = MyClass()

#print (len(A))
print (A is B)

這樣也可以

# singleton
instances = None
def singleton(cls):
    def getinstance(*args, **kwargs):
        global instances
        if not instances:
           instances = cls(*args, **kwargs)
        return instances
    return getinstance

@singleton
class MyClass():
    a = 1

A = MyClass()
B = MyClass()

#print (len(A))
print (A is B)

但是這樣不行

# singleton
def singleton(cls):
    instance = None
    def getinstance(*args, **kwargs):
        if not instance:
           instance = cls(*args, **kwargs)
        return instance
    return getinstance

@singleton
class MyClass():
    a = 1

A = MyClass()
B = MyClass()

#print (len(A))
print (A is B)

為什么?因為這里構(gòu)成了閉包,Python只會會把閉包中用到的值保存下來,但是你不能在閉包中對其進(jìn)行修改。也就是說在這個例子里,你只能訪問instance,但是不能對其賦值,否則會報錯UnboundLocalError。我會在另外一篇關(guān)于作用域和閉包的文章中仔細(xì)講一講。

怎么改呢?一種就是用上面的兩種方法,將它改成一個列表或者字典,我們不能對列表本身做修改,但是可以對列表中包含的對象做修改;另一種方法則是用關(guān)鍵詞nonlocal:

# singleton
def singleton(cls):
    instance = None
    def getinstance(*args, **kwargs):
        nonlocal instance
        if not instance:
           instance = cls(*args, **kwargs)
        return instance
    return getinstance

@singleton
class MyClass():
    a = 1

A = MyClass()
B = MyClass()

#print (len(A))
print (A is B)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容