Python版設計模式之單例模式

單例模式

在某些場景下,我們希望實體類無論實例化多少次都只會產生一個實體對象,這時候就需要使用單例模式。經常使用的場景就是全局配置類。

模式框架

  • 方式1:使用修飾器
"""使用函數定義裝飾器"""
def singletons(cls):
    """
    定義一個單例裝飾器,使用dict保存定義好的實體,key爲class的地址而不是名字,這樣同名類也不會衝突
    """
    instances = {}

    def wrapper(*args, **kwargs):
        if cls not in instances.keys():
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper
"""使用類定義裝飾器"""
class singletons(object):
    instances = {}

    def __init__(self, cls):
        self.__cls = cls

    def __call__(self, *args, **kwargs):
        if self.__cls not in singletons.instances.keys():
            singletons.instances[self.__cls] = self.__cls(*args, **kwargs)
        return singletons.instances[self.__cls]
  • 方式2:重寫__new__方法,只能針對當前修改的類有效
class SingletonTest(object):

    __instance = None
    __isFirstInit = False

    def __new__(cls, name):
        if not cls.__instance:
            SingletonTest.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self, name):
        if not self.__isFirstInit:
            self.__name = name
            SingletonTest.__isFirstInit = True

    def getName(self):
        return self.__name

UML圖

clipboard.png

示例

@singletons
class Test(object):
    def __init__(self, name):
        self.__name = name

    def hello(self):
        print("I am {} object {}".format(self.__name, id(self)))


if __name__ == "__main__":
    test1 = Test("test1")
    test2 = Test("test2")
    test1.hello()
    test2.hello()
'''測試輸出'''
# I am test1 object 2453169112512
# I am test1 object 2453169112512

擴展思考

  1. 單例模式的線程安全問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章