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图

Python版设计模式之单例模式

示例

@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. 单例模式的线程安全问题。

相关推荐