什么是单例模式(Singleton)?
单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。
如何实现单例的方式?(四种方法)
- 全局变量:不直接调用 Config() ,而使用同一个全局变量
- 重写 __new__ 方法:重写 __new__ 来保证每次调用 Config() 都会返回同一个对象,__new__为对象分配空间,返回对象的引用
- 使用metaclass:metaclass重写__call__ 方法来保证每次调用 Config() 都会返回同一个对象
- 使用装饰器:使用装饰器来保证每次调用 Config() 都会返回同一个对象
原理:在真正调用 Config() 之前进行一些拦截操作,来保证返回的对象都是同一个:
1. 全局变量
# config.py
from dataclasses import dataclass
@dataclass
class Config:
SQLALCHEMY_DB_URI = SQLALCHEMY_DB_URI
config = Config(SQLALCHEMY_DB_URI = "mysql://"``)
通过使用全局变量,我们在所有需要引用配置的地方,都使用 from config import config 来导入,这样就达到了全局唯一的目的。
2. 重写new方法
class Singleton(object):
_instance = None # _instance 作为类属性,保证了所有对象的实例都是同一个
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls) # 为对象分配空间
return cls._instance # 返回对象的引用
a = Singleton() # 创建对象时,new方法会被自动调用
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x0000023A88E0F2B0>
<__main__.Singleton object at 0x0000023A88E0F2B0>
每次实例化一个对象时,都会先调用 __new__()
创建一个对象,再调用 __init__()
函数初始化数据。因而,在 new 函数中判断 Singleton类 是否已经实例化过,如果不是,调用父类的 new 函数创建实例;否则返回之前创建的实例。
3. 使用metaclass元类
class SigletonMetaClass(type):
_instance = None
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def __call__(self, *args, **kwargs):
if self._instance is None:
self._instance = super().__call__(*args, **kwargs)
return self._instance
class Singleton(metaclass=SigletonMetaClass):
def __new__(cls, *args, **kwargs):
return super().__new__(cls)
a = Singleton()
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x000001A11E4AC908>
<__main__.Singleton object at 0x000001A11E4AC908>
因此,用元类实现单例时仍需按照三步骤:1. 拦截 2. 判断是否已经创建过对象 3. 返回对象。与上个方法相比,区别在于拦截的地点不同。
4. 装饰器
4.1 函数装饰器
def SingletonDecorator(cls):
_instance = None
def get_instance(*args, **kwargs):
nonlocal _instance
if _instance is None:
_instance = cls(*args, **kwargs)
return _instance
return get_instance
@SingletonDecorator
class Singleton(object):
pass
a = Singleton()
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x0000022194E6C438>
<__main__.Singleton object at 0x0000022194E6C438>
4.2 类装饰器
class SingletonDecorator(object):
_instance = None
def __init__(self, cls):
self._cls = cls
def __call__(self, *args, **kwargs):
if self._instance is None:
self._instance = self._cls(*args, **kwargs)
return self._instance
@SingletonDecorator
class Singleton(object):
pass
a = Singleton()
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x0000028F42CFC8D0>
<__main__.Singleton object at 0x0000028F42CFC8D0>