什么是单例模式?

主要目的是确保一个类只有一个实例存在
例如调用一个配置文件(AppConfig类),加入需要使用该配置的地方很多,需要实例化很多个实例对象,就会浪费内存资源,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象
单例模式保证了程序的不同位置都可以且仅可以取到同一个对象实例,如果实例不存在,会创建一个实例,如果已经存在则会返回这个实例

使用函数装饰器实现

  1. def single(cls):
  2. _instance = {}
  3. def inner():
  4. if cls not in _instance:
  5. _instance[cls] = cls()
  6. return _instance[cls]
  7. return inner
  8. @single
  9. class Cls:
  10. def __init__(self):
  11. pass
  12. cls1 = Cls()
  13. cls2 = Cls()
  14. print(id(cls1) == id(cls2))
  15. -------------------
  16. #True

使用类装饰器

  1. class Single:
  2. def __init__(self, cls):
  3. self._cls = cls
  4. self._instance = {}
  5. def __call__(self):
  6. if self._cls not in self._instance:
  7. self._instance[self._cls] = self._cls()
  8. return self._instance[self._cls]
  9. @Single
  10. class Cls2:
  11. def __init__(self):
  12. pass
  13. cls1 = Cls2()
  14. cls2 = Cls2()
  15. print(id(cls1) == id(cls2))
  16. -----------
  17. #True

基于new()方法

我们实例化对象时,会先调用new(),实例化对象,没有写就是默认调用了object.new, 然后再调用init方法,初始化对象
使用 new 方法在创造实例时进行干预,达到实现单例模式的目的

  1. import threading
  2. class Singleton:
  3. #加锁,防止多线程获取对象时创建过多实例
  4. _instance_lock = threading.Lock()
  5. def __init__(self):
  6. pass
  7. def __new__(cls, *args, **kwargs):
  8. #判断是否存在实例,如果存在,返回实例,如果不存在就创建
  9. if not hasattr(singleton, "_instance"):
  10. with Singleton._instance_lock:
  11. if not hasattr(Singleton, "_instance"):
  12. Singleton._instance = object.__new__(cls)
  13. return Singleton._instance
  14. obj1 = Singleton()
  15. obj2 = Singleton()
  16. print(obj1, '\n', obj2)
  17. def task(arg):
  18. obj = Singleton()
  19. print(obj)
  20. for i in range(10):
  21. t = threading.Thread(target=task, args=[i, ])
  22. t.start()

基于元类(mateclass)

1.类由type创建,创建类时,type的init方法自动执行,类() 执行type的 call方法(类的new方法,类的init方法)
2.对象由类创建,创建对象时,类的init方法自动执行,对象()执行类的 call 方法

  1. class Foo:
  2. def __init__(self):
  3. pass
  4. def __call__(self, *args, **kwargs):
  5. pass
  6. obj = Foo()
  7. # 执行type的 __call__ 方法,调用 Foo类(是type的对象)的 __new__方法,用于创建对象,然后调用 Foo类(是type的对象)的 __init__方法,用于对对象初始化。
  8. obj() # 执行Foo的 __call__ 方法

元类的使用:

  1. class SingletonType(type):
  2. def __init__(self,*args,**kwargs):
  3. super(SingletonType,self).__init__(*args,**kwargs)
  4. def __call__(cls, *args, **kwargs): # 这里的cls,即Foo类
  5. print('cls',cls)
  6. obj = cls.__new__(cls,*args, **kwargs)
  7. cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj)
  8. return obj
  9. class Foo(metaclass=SingletonType): # 指定创建Foo的type为SingletonType
  10. def __init__(selfname):
  11. self.name = name
  12. def __new__(cls, *args, **kwargs):
  13. return object.__new__(cls)
  14. obj = Foo('xx')

同样,我们在类的创建时进行干预,从而达到实现单例的目的。

  1. class Singleton(type):
  2. _instances = {}
  3. def __call__(cls, *args, **kwargs):
  4. if cls not in cls._instances:
  5. cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
  6. return cls._instances[cls]
  7. class Cls4(metaclass=Singleton):
  8. pass
  9. cls1 = Cls4()
  10. cls2 = Cls4()
  11. print(id(cls1) == id(cls2))
  12. ---------
  13. #True
  14. # 实现单例模式实例2
  15. import threading
  16. class SingletonType(type):
  17. _instance_lock = threading.Lock()
  18. def __call__(cls, *args, **kwargs):
  19. if not hasattr(cls, "_instance"):
  20. with SingletonType._instance_lock:
  21. if not hasattr(cls, "_instance"):
  22. cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
  23. return cls._instance
  24. class Foo(metaclass=SingletonType):
  25. def __init__(self,name):
  26. self.name = name
  27. obj1 = Foo('name')
  28. obj2 = Foo('name')
  29. print(obj1,obj2)

导入模块

python中的模块导入,第一次导入会生成 .pyc文件,第二次导入则会直接加载 .pyc文件,如果要实现单例,则只需要将要实现单例的类定义在一个模块,然后导入。

参考:https://www.cnblogs.com/huchong/p/8244279.html,https://zhuanlan.zhihu.com/p/37534850
参考:https://www.cnblogs.com/fiona-zhong/p/10365134.html