什么是单例模式?
主要目的是确保一个类只有一个实例存在
例如调用一个配置文件(AppConfig类),加入需要使用该配置的地方很多,需要实例化很多个实例对象,就会浪费内存资源,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象
单例模式保证了程序的不同位置都可以且仅可以取到同一个对象实例,如果实例不存在,会创建一个实例,如果已经存在则会返回这个实例
使用函数装饰器实现
def single(cls):_instance = {}def inner():if cls not in _instance:_instance[cls] = cls()return _instance[cls]return inner@singleclass Cls:def __init__(self):passcls1 = Cls()cls2 = Cls()print(id(cls1) == id(cls2))-------------------#True
使用类装饰器
class Single:def __init__(self, cls):self._cls = clsself._instance = {}def __call__(self):if self._cls not in self._instance:self._instance[self._cls] = self._cls()return self._instance[self._cls]@Singleclass Cls2:def __init__(self):passcls1 = Cls2()cls2 = Cls2()print(id(cls1) == id(cls2))-----------#True
基于new()方法
我们实例化对象时,会先调用new(),实例化对象,没有写就是默认调用了object.new, 然后再调用init方法,初始化对象
使用 new 方法在创造实例时进行干预,达到实现单例模式的目的
import threadingclass Singleton:#加锁,防止多线程获取对象时创建过多实例_instance_lock = threading.Lock()def __init__(self):passdef __new__(cls, *args, **kwargs):#判断是否存在实例,如果存在,返回实例,如果不存在就创建if not hasattr(singleton, "_instance"):with Singleton._instance_lock:if not hasattr(Singleton, "_instance"):Singleton._instance = object.__new__(cls)return Singleton._instanceobj1 = Singleton()obj2 = Singleton()print(obj1, '\n', obj2)def task(arg):obj = Singleton()print(obj)for i in range(10):t = threading.Thread(target=task, args=[i, ])t.start()
基于元类(mateclass)
1.类由type创建,创建类时,type的init方法自动执行,类() 执行type的 call方法(类的new方法,类的init方法)
2.对象由类创建,创建对象时,类的init方法自动执行,对象()执行类的 call 方法
class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):passobj = Foo()# 执行type的 __call__ 方法,调用 Foo类(是type的对象)的 __new__方法,用于创建对象,然后调用 Foo类(是type的对象)的 __init__方法,用于对对象初始化。obj() # 执行Foo的 __call__ 方法
元类的使用:
class SingletonType(type):def __init__(self,*args,**kwargs):super(SingletonType,self).__init__(*args,**kwargs)def __call__(cls, *args, **kwargs): # 这里的cls,即Foo类print('cls',cls)obj = cls.__new__(cls,*args, **kwargs)cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj)return objclass Foo(metaclass=SingletonType): # 指定创建Foo的type为SingletonTypedef __init__(self,name):self.name = namedef __new__(cls, *args, **kwargs):return object.__new__(cls)obj = Foo('xx')
同样,我们在类的创建时进行干预,从而达到实现单例的目的。
class Singleton(type):_instances = {}def __call__(cls, *args, **kwargs):if cls not in cls._instances:cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)return cls._instances[cls]class Cls4(metaclass=Singleton):passcls1 = Cls4()cls2 = Cls4()print(id(cls1) == id(cls2))---------#True# 实现单例模式实例2import threadingclass SingletonType(type):_instance_lock = threading.Lock()def __call__(cls, *args, **kwargs):if not hasattr(cls, "_instance"):with SingletonType._instance_lock:if not hasattr(cls, "_instance"):cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)return cls._instanceclass Foo(metaclass=SingletonType):def __init__(self,name):self.name = nameobj1 = Foo('name')obj2 = Foo('name')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
