2026-05-10
Python 设计模式 —— 单例模式

单例模式的概念
单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例.
核心概念
想象一下公司的 CEO 职位 – 整个公司只能有一个 CEO,无论哪个部门需要向 CEO 汇报,他们访问的都是同一个 CEO 对象。单例模式就是编程世界中的”CEO 职位管理机制”.
为什么需要单例模式
在实际开发中,有些对象我们只需要一个实例就足够了,比如:
- 配置管理器:整个应用程序共享同一套配置
- 数据库连接池:避免重复创建连接,节省资源
- 日志记录器:确保所有日志都写入同一个文件
- 缓存系统:统一管理缓存数据
Python 具体实现方法
模块
Python 的模块默认采用单例模式,也就是只初始化一次,多次 import 并不会多次导入. 例如:
Python
# 单例模式的实现方式:导入模块
# 数据库例子
class DatabaseConnection:
def __init__(self):
self.connection_string = "database://localhost:5432/mydb"
print("数据库连接已创建")
def query(self, sql):
return f"执行查询: {sql}"
# 创建单例实例
db_instance = DatabaseConnection()
此时在另一个文件导入:
Python
from singleton_module import db_instance
# 只暴露 db_instance 接口,保证单例
print(db_instance.query("SELECT * FROM data;"))
此时 db_instance 是唯一的单例,接口只暴露它的话就实现了单例模式.
魔法方法 __new__
这里为 class 新增一个 _instance (什么名字都行),用于缓存真正的单例,第一次初始化就负责创建并存放单例,后面的初始化都只返回缓存即可:
Python
class DatabaseConnection:
_instance = None
def __init__(self):
self.connection_string = "database://localhost:5432/mydb"
print("数据库连接已创建")
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
print("创建新实例")
else:
print("返回已有实例")
return cls._instance
def query(self, sql):
return f"执行查询: {sql}"
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)
装饰器
使用 Python 的装饰器可以非常简洁地实现,并且可复用,更推荐这种做法,方便解耦.
Python
def singleton(cls):
"""单例装饰器"""
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class DatabaseConnection:
_instance = None
def __init__(self):
self.connection_string = "database://localhost:5432/mydb"
print("数据库连接已创建")
def query(self, sql):
return f"执行查询: {sql}"
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)
这里进行一下解析,装饰器一般通过返回一个内部函数,调用的时候就类似 DatabaseConnection = singleton(DatabaseConnection) ,原理还是和 __new__ 方法一样,创建缓存来存放单例.
单例模式的缺陷
- 需要单元测试的时候,无法使用单例模式,因为测试会更改单例的状态;
- 多线程情况下,由于两个线程之间同时调用
__new__的时候,可能同时创建两个不同的实例,会破坏单例模式,因此需要加线程锁. - 需要多态的时候应该尽量避免单例模式.