单例模式是最常被提及、也最容易被误用的设计模式之一。
在 Python 中,由于语言特性特殊,单例模式既简单,也容易踩坑。
本篇我们重点解决三个问题:
- 单例模式到底解决什么问题
- Python 中有哪些实现方式
- 哪些场景真的适合用单例
一、什么是单例模式
单例模式(Singleton) 的定义很简单:
保证一个类在系统中只有一个实例,并提供全局访问点。
核心目标只有两个:
二、为什么需要单例模式
在实际项目中,以下对象往往只需要一个实例:
- 配置中心
- 日志对象
- 数据库连接池
- 缓存管理器
- 全局状态管理器
如果这些对象被反复创建,可能带来:
三、最“Python 风格”的单例:模块即单例
在 Python 中,模块天然是单例的。
# config.py
class Config:
DEBUG = True
# main.py
from config import Config
解释:
- 模块只会被加载一次
- 多次
import 返回的是同一个模块对象
✅ 推荐指数:★★★★★
如果能用模块解决,不要写复杂单例代码。
四、基于 __new__ 的经典单例实现
当你必须使用类时,最常见的是重写 __new__。
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
测试:
a = Singleton()
b = Singleton()
print(a is b) # True
特点:
- 控制实例创建过程
- 逻辑清晰,易理解
- 是讲解单例原理的最佳示例
五、线程安全的单例(加锁版)
在多线程环境中,上面的实现并不安全。
import threading
class Singleton:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
适用场景:
单例模式是最常被提及、也最容易被误用的设计模式之一。
在 Python 中,由于语言特性特殊,单例模式既简单,也容易踩坑。
本篇我们重点解决三个问题:
- 单例模式到底解决什么问题
- Python 中有哪些实现方式
- 哪些场景真的适合用单例
一、什么是单例模式
单例模式(Singleton) 的定义很简单:
保证一个类在系统中只有一个实例,并提供全局访问点。
核心目标只有两个:
二、为什么需要单例模式
在实际项目中,以下对象往往只需要一个实例:
- 配置中心
- 日志对象
- 数据库连接池
- 缓存管理器
- 全局状态管理器
如果这些对象被反复创建,可能带来:
三、最“Python 风格”的单例:模块即单例
在 Python 中,模块天然是单例的。
# config.py
class Config:
DEBUG = True
# main.py
from config import Config
解释:
- 模块只会被加载一次
- 多次
import 返回的是同一个模块对象
✅ 推荐指数:★★★★★
如果能用模块解决,不要写复杂单例代码。
四、基于 __new__ 的经典单例实现
当你必须使用类时,最常见的是重写 __new__。
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
测试:
a = Singleton()
b = Singleton()
print(a is b) # True
特点:
- 控制实例创建过程
- 逻辑清晰,易理解
- 是讲解单例原理的最佳示例
五、线程安全的单例(加锁版)
在多线程环境中,上面的实现并不安全。
import threading
class Singleton:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
适用场景:
六、装饰器方式实现单例
利用 Python 的函数闭包特性:
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:
pass
特点:
七、元类实现单例(了解即可)
元类控制的是类的创建行为:
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 Config(metaclass=SingletonMeta):
pass
适合:
❗ 日常业务代码中不推荐滥用。
八、单例模式的常见误区
1. 把单例当全局变量用
2. 所有“全局对象”都做成单例
判断标准只有一个:
系统中是否逻辑上只允许存在一个实例?
3. 忽略生命周期管理
单例≠永远存在
尤其在长生命周期服务中,要考虑:
九、什么时候该用单例,什么时候不该用
适合使用:
不适合使用:
- 业务对象(订单、用户、商品)
- 状态频繁变化的对象
- 需要大量 Mock 测试的组件
十、总结
单例模式在 Python 中:
- 实现方式多
- 模块方式最优先
- 能不用就不用,用就用清楚
理解单例的关键不在“怎么写”,而在于:
你是否真的需要系统中只有一个实例。