单例模式
1. 什么是单例模式
单例模式保证一个类只有一个实例,并且需要为该实例提供一个全局访问节点。
2. 实现
装饰器实现(线程不安全):
python
def singleton(cls: type) -> type:
_instances = {}
def get_instance(*args, **kwargs):
if cls not in _instances:
_instances[cls] = cls(*args, **kwargs)
return _instances[cls]
return get_instance
@singleton
class Singleton:
...
装饰器实现(线程安全):
python
from threading import Lock
def singleton(cls: type) -> type:
_instances = {}
lock = Lock()
def get_instance(*args, **kwargs):
with lock:
if cls not in _instances:
_instances[cls] = cls(*args, **kwargs)
return _instances[cls]
return get_instance
元类实现(线程不安全):
python
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
...
元类实现(线程安全):
python
from threading import Lock
class SingletonMeta(type):
_instances = {}
lock = Lock()
def __call__(cls, *args, **kwargs):
with cls.lock:
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
...
推荐使用元类实现单例模式。
有时我们希望抽象类的子类也是单例,这时使用元类实现会出错,元类必须是抽象类的子类,这时我们可以构造 ABCSingletonMeta
来解决这个问题:
python
from abc import ABCMeta
class ABCSingletonMeta(ABCMeta, SingletonMeta):
...
class BaseSingleton(metaclass=ABCSingletonMeta):
...
此时,我们可以将 ABCSingletonMeta
作为抽象类的元类,这样抽象类的子类也可以是单例。