单例模式¶
保证一个类仅有一个实例,并提供一个访问它的全局访问点。比如在 Windows 系统中,任务管理器就是单例模式的应用,无论在系统的任何地方调用任务管理器,都是同一个实例。
使用场景¶
- 数据库连接池
- 日志记录器
- 配置管理器
- 线程池
- 缓存系统
通过 __new__
方法控制实例化推荐
¶
class Singleton:
_instance = None # 类属性保存唯一实例
def __new__(cls, *args, **kwargs):
if not cls._instance:
# 首次创建实例时调用基类的 __new__
cls._instance = super().__new__(cls)
return cls._instance # 始终返回同一个实例
def __init__(self, config):
# 防止重复初始化
if not hasattr(self, '_initialized'):
self.config = config
self._instance = True
# 使用示例
s1 = Singleton(config='DB_config')
s2 = Singleton(config='New_config')
print(s1 is s2)
print(s1.config)
True
New_config
装饰器¶
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Logger:
def __init__(self, log_file):
self.log_file = log_file
logger1 = Logger('app.log')
logger2 = Logger('new.log')
print(logger1 is logger2)
print(logger1.log_file)
True
app.log
通过元类¶
# 方法3 通过元类
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
def __init__(self, connection_string):
self.conn = self._connect(connection_string)
def _connect(self, conn_str):
print(f'Connecting to {conn_str}...')
return 'Connection object'
# 使用示例
db1 = DatabaseConnection("mysql://user:pwd@localhost")
db2 = DatabaseConnection("postgres://user:pwd@localhost")
print(db1 is db2) # 输出: True
print(db1.conn) # 输出: "Connection Object"
Connecting to mysql://user:pwd@localhost...
True
Connection object
- 定义单例类,重写
__new__
方法,确保只创建一个实例。- 在类的初始化方法
__init__
中检查是否已初始化,避免重复初始化。- 提供示例代码,展示如何创建实例并验证其唯一性。
- 简要讨论其他实现方式,如使用装饰器或元类。
- 提及线程安全和其他注意事项