Python中创建一个动态调度的单例类

148 阅读1分钟

前述

在近日的日常开发中,有一个需求是通过外部的配置项来控制当前的类是否使用单例模式.

普通的单例实现

个人觉得最常用的就是可以通过__new__来实现,python在加载类实例的时候会先调用__new__函数的代码实现。

class SingletonClass(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(SingletonClass, cls).__new__(cls)  
        return cls._instance
 
    def __init__(self, name):
        self.name = name

元类实现

通过用__new__来实现单例,并不能满足我的需求,这里我们可以通过元类来动态的设置类的单例模式

config_item = True

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if not config_item:
            if cls not in cls._instances:
                cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
            return cls._instances[cls]
        else:
            return super(SingletonMeta, cls).__call__(*args, **kwargs)


class MyClass(metaclass=SingletonMeta):
    def __init__(self, value):
        self.value = value


if __name__ == "__main__":  
    # 第一次创建实例  
    instance1 = MyClass(10)  
    print(instance1)  # 输出: MyClass(value=10)  
  
    # 测试配置项为True的情况  
    config_item = True  
    instance2 = MyClass(20)  
    print(instance2)  # 若配置项为True,输出: MyClass(value=10)  
    print(instance1 is instance2)  # 输出: True  
  1. 外部(全局)变量:用于控制是否使用单例模式。

  2. 元类 SingletonMeta

    • 使用 _instances 字典来存储单例实例。
    • 重写 __call__ 方法,该方法在类实例化时被调用。
    • 根据 USE_SINGLETON 的值决定是返回现有实例还是创建新实例。
  3. 类 MyClass:使用 SingletonMeta 作为其元类。

通过这种方式,可以动态地控制类是否应该使用单例模式。