单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
比如在Django开发中,我们会用到短信验证的业务,如果我们有成千上万的用户同时有发送短信的需求,那么我们就需要创建成千上万的发送短信的对象,实际上只需要调用对象的方法进行发送短信罢了,因此采用单例模式就可以减少创建多余的类对象,节省资源!
本文以5种方式实现单例模式,分别是:使用__new__实现单例,使用元类创建单例,使用函数装饰器实现单例,使用类装饰器实现单例以及import方法。
# 使用__new__()实现单例
class A():
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
a1 = A() # 在创建实例之前会调用__new__()方法
a2 = A()
print(a1, a2)
print(id(a1), id(a2))
print(a1 is a2)
<__main__.A object at 0x000002B48233F4E0> <__main__.A object at 0x000002B48233F4E0>
2974301811936 2974301811936
True
# 使用元类创建单例
class B(type):
def __init__(self, *args, **kwargs):
self._instance = None
def __call__(self, *args, **kwargs):
if not self._instance:
self._instance = super().__call__(*args, **kwargs)
return self._instance
class C(metaclass=B): # <==> C = B(xx)
pass
c1 = C() # <==> c1 = C() = B(xx)(): 调用__call__方法
c2 = C()
print(c1, c2)
print(id(c1), id(c2))
print(c1 is c2)
<__main__.C object at 0x000002B48233FC88> <__main__.C object at 0x000002B48233FC88>
2974301813896 2974301813896
True
# 使用装饰器实现单例
def setfunc(cls):
instance = {}
def callfunc(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return callfunc
@setfunc
class D(): # <==> D = setfunc(D)
pass
d1 = D() # <==> d1 = D() = setfunc(D)() = callfunc()
d2 = D()
print(d1, d2)
print(id(d1), id(d2))
print(d1 is d2)
<__main__.D object at 0x000002B48233FDA0> <__main__.D object at 0x000002B48233FDA0>
2974301814176 2974301814176
True
# 使用类装饰器实现单例
class Single():
def __init__(self, _class):
self._class = _class
self._instance = {}
def __call__(self):
if self._class not in self._instance:
self._instance[self._class] = self._class()
return self._instance[self._class]
@Single
class E(): # <==> E = Single(E)
pass
e1 = E() # <==> e1 = E() = Single(E)() ==> 调用__call__()方法
e2 = E()
print(e1, e2)
print(id(e1), id(e2))
print(e1 is e2)
<__main__.E object at 0x000002B482348128> <__main__.E object at 0x000002B482348128>
2974301847848 2974301847848
True