单例模式
什么是单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
单例模式的实现
python实现单例模式有多种实现方法,下面一一来解释说明
1. 基于装饰器的单例模式的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| def singleton(cls): _instance = {}
def _singleton(*args, **kwargs): if cls not in _instance: _instance[cls] = cls(*args, **kwargs) return _instance[cls]
return _singleton
@singleton class A(object): a = 1
def __init__(self, x=0): self.x = x print('这是A的类的初始化方法')
a1 = A(2) a2 = A(3) print(a1.x, a2.x) print(id(a1), id(a2))
|
可以看到打印结果为:
2. 基于类方法的单例模式的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class A:
def __init__(self, x, y): self.x = x self.y = y
@classmethod def singleton(cls, *args, **kwargs): if not hasattr(cls, '__instance'): cls.__instance = cls(*args, **kwargs) return cls.__instance
obj1 = A(1, 2) obj2 = A(3, 4) print(obj1.x, obj1.y, obj2.x, obj2.y) print(id(obj1), id(obj2)) obj3 = A.singleton(1, 2) obj4 = A.singleton(3, 4) print(obj3.x, obj3.y, obj4.x, obj4.y) print(id(obj3), id(obj4)
|
打印结果如下:
但是这个实现方法在多线程上会出现堵塞现象,所以需要加锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import threading
class A: _instance_lock = threading.Lock()
def __init__(self, x, y): self.x = x self.y = y
@classmethod def singleton(cls, *args, **kwargs): if not hasattr(cls, '__instance'): with cls._instance_lock: cls.__instance = cls(*args, **kwargs) return cls.__instance
obj1 = A(1, 2) obj2 = A(3, 4) print(obj1.x, obj1.y, obj2.x, obj2.y) print(id(obj1), id(obj2)) obj3 = A.singleton(1, 2) obj4 = A.singleton(3, 4) print(obj3.x, obj3.y, obj4.x, obj4.y) print(id(obj3), id(obj4))
|
可以发现,使用类方法创建单例模式时,必须要调用该方法,否则直接调用类得到的并不是单例
3. 基于new方法实现单例模式(推荐)
一个对象的实例化过程是先执行类的new方法,如果我们没有写,默认会调用object的new方法,返回一个实例化对象,然后再调用init方法,对这个对象进行初始化,我们可以根据这个实现单例.
在一个类的new方法中先判断是不是存在实例,如果存在实例,就直接返回,如果不存在实例就创建.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import threading
class A: _instance_lock = threading.Lock()
def __new__(cls, *args, **kwargs): if not hasattr(cls, '__instance'): with cls._instance_lock: if not hasattr(cls, '__instance'): cls.__instance = super().__new__(cls) return cls.__instance
obj1 = A() obj2 = A() print(obj1, obj2) print(id(obj1), id(obj2))
|
类由type创建,创建类时,type的init方法自动执行,类() 执行type的 call方法(类的new方法,类的init方法)
对象由类创建,创建对象时,类的init方法自动执行,对象()执行类的 call 方法
1 2 3 4 5 6 7 8 9 10 11
| class Foo: def __init__(self): pass
def __call__(self, *args, **kwargs): pass
obj = Foo()
obj()
|
元类的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class SingletonType(type): def __init__(self,*args,**kwargs): super(SingletonType,self).__init__(*args,**kwargs)
def __call__(cls, *args, **kwargs): print('cls',cls) obj = cls.__new__(cls,*args, **kwargs) cls.__init__(obj,*args, **kwargs) return obj
class Foo(metaclass=SingletonType): def __init__(self,name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls)
obj = Foo('xx')
|
实现单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import threading
class 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._instance
class Foo(metaclass=SingletonType): def __init__(self,name): self.name = name
obj1 = Foo('name') obj2 = Foo('name') print(obj1,obj2)
|