Skip to content

单例模式

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 作为抽象类的元类,这样抽象类的子类也可以是单例。