python進階篇--實現單例的方法

單例是設計模式中一個比較簡單但又比較重要的一個概念。今天讓我們來一起看一下,python中實現單例的幾種方法。

方案一:通過一個cahcemanager 來緩存類實例,這個是針對多個實例但是不重複的例子。

import weakref


class CacheManager:
    def __init__(self):
        self._cache = weakref.WeakValueDictionary()

    def get_test(self, name):
        if name not in self._cache:
            temp = Test._new(name)
            self._cache[name] = temp
        else:
            temp = self._cache[name]

        return temp


class Test:
    def __init__(self):
        raise RuntimeError("Cannot instantiate directly")

    @classmethod
    def _new(cls, name):
        self = cls.__new__(cls)
        self.name = name
        return self

    def show(self):
        print("The Test name is {0}".format(self.name))


if __name__ == "__main__":
    cache = CacheManager()
    test_abc = cache.get_test("abc")
    test_abc.show()

    test_abc2 = cache.get_test("abc")

    if test_abc is test_abc2:
        print("They are the same class")

方案二:使用類裝飾器, 真正的一個類只有一個實例。

from functools import wraps


def singleton(cls):
    instance = {}

    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]
    return wrapper

@singleton
class Test:
    def __init__(self, name):
        print("__init__")
        self.name = name

    def show(self):
        print("The test name is {0}".format(self.name))


if __name__ == "__main__":
    test1 = Test("abc")
    test2 = Test("abc")
    if test1 is test2:
        print("They are the same class")

方案三:高端手法,使用元類。優雅實現方案一

import weakref


class Cached(type):

    def __init__(cls, *args, **kwargs):
        super().__init__(*args, **kwargs)
        cls.__cached = weakref.WeakValueDictionary()

    def __call__(cls, *args):
        if args in cls.__cached:
            return cls.__cached[args]
        else:
            obj = super().__call__(*args)
            cls.__cached[args] = obj
            return cls.__cached[args]


class Spam(metaclass=Cached):
    def __init__(self, name):
        print("Creating Spam")
        self.name = name


if __name__ == "__main__":
    a = Spam("Wang")
    b = Spam("Wang")

    if a is b:
        print("They are the same class")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章