單例模式

什麼是單例模式

  • 單例,即單個實例,一個類在實例化的過程中始終返回同一個實例

實現單例模式的四種方法

  • 重寫__new__(cls)方法,該方法是一個類方法,用來爲實例開闢內存空間,返回值是實例化對象,通過重寫該方法,可以使每次實例化都返回同一個對象
  • 修飾器方法:與之前修飾器那一節的斐波那契數列類似,判斷字典中有沒有對象,有的話就直接返回,沒有才實例化
  • 模塊:這是最簡單的方法,直接導入實例化對象
  • 共享屬性:通過把所有對象的__dict__指向同一塊內存空間來實現,雖然不是“一個實例”,但其行爲與“一個實例”一樣

實現單例設計的方法

重寫__new__()

class Foo:
    def __new__(cls,*args, **kwargs):
        # 如果是第一次實例化,返回一個新對象
        if not hasattr(cls, '_object'):
            cls._object = super().__new__(cls)
        return cls._object

    def __init__(self, name):
            self.name = name

    def Print(self):
        print(f'The name of this object is: {self.name}')

if __name__ == '__main__':
    foo1 = Foo('foo1')
    foo2 = Foo('foo2')
    foo3 = Foo('foo3')
    foo1.Print()  # The name of this object is: foo3
    foo2.Print()  # The name of this object is: foo3
    foo3.Print()  # The name of this object is: foo3

使用裝飾器

def singleton(cls):
    singleton_dict = {}
    def close(*args, **kwargs):
    # 利用字典的setdefault()方法,如果第一次實例化就加入字典,以後每次都返回這個對象
        return singleton_dict.setdefault('obj',cls(*args, **kwargs))
    return close

@singleton
class MyClass:
    pass

if __name__ == '__main__':
    foo1 = MyClass()
    foo2 = MyClass()
    print(foo1)  # <__main__.MyClass object at 0x000001DF618C8940>
    print(foo2)  # <__main__.MyClass object at 0x000001DF618C8940>

使用模塊

用import導入的模塊就是天然的單例模式,如果想要實現一個單例類,不妨把它作爲一個獨立的模塊,使用時導入由他實例化出來的對象

# mysingleton.py
class My_Singleton(object):
    def foo(self):
        pass

my_singleton = My_Singleton()

# to use
from mysingleton import my_singleton

my_singleton.foo()

共享屬性

共享屬性是指所有由“單例類”實例化出來的對象都共享“同一份屬性”,也就是所有對象的__dict__都指向同一個字典,但這樣嚴格來說並不算真的單例模式,因爲這樣還是有多個實例對象,但其行爲確實和單例模式一樣

class Foo:
    _mydict = {}
    def __new__(cls, *args, **kwargs):
        ob = super().__new__(cls)
        ob.__dict__ = cls._mydict
        return ob

    if __name__ == '__main__':
        foo1 = Foo()
        foo2 = Foo()
        foo1.name = 'foo1'
        print(foo2.name)  # foo1
        # foo1 和 foo2 並不是同一個對象,只不過他們的方法和屬性公用同一塊內存
        print(foo1)  # <__main__.Foo object at 0x0000023ADA4A8A90>
        print(foo2)  # <__main__.Foo object at 0x0000023ADA4A8AC8>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章