Python编程:单例模式
·
单例模式(Singleton Pattern)是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。
单例模式基础实现
1. 模块级单例(最简单实现)
# singleton.py
class _Singleton:
def __init__(self):
self.value = None
def __str__(self):
return f"Singleton with value: {self.value}"
instance = _Singleton()
# 使用示例
from singleton import instance
instance.value = 42
print(instance) # 输出: Singleton with value: 42
特点:
-
Python模块天然就是单例
-
导入时创建,线程安全
-
最简单直接的实现方式
2. 装饰器实现
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 Logger:
def __init__(self):
self.logs = []
def add_log(self, message):
self.logs.append(message)
# 使用示例
logger1 = Logger()
logger2 = Logger()
logger1.add_log("First log")
print(logger2.logs) # 输出: ['First log']
print(logger1 is logger2) # 输出: True
线程安全的单例模式
1. 加锁实现线程安全
import threading
class ThreadSafeSingleton:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if not cls._instance:
with cls._lock:
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
# 使用示例
def test_singleton():
singleton = ThreadSafeSingleton()
print(id(singleton))
threads = [threading.Thread(target=test_singleton) for _ in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
2. 基于元类的线程安全实现
import threading
class SingletonMeta(type):
_instances = {}
_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
with cls._lock:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
def __init__(self):
self.connection = "Established"
def query(self, sql):
return f"Executing: {sql}"
# 使用示例
db1 = Database()
db2 = Database()
print(db1 is db2) # 输出: True
print(db1.query("SELECT * FROM users")) # 输出: Executing: SELECT * FROM users
单例模式高级应用
1. 单例与继承
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
class ConfigManager(Singleton):
def __init__(self):
if not hasattr(self, 'config'):
self.config = {}
def set_config(self, key, value):
self.config[key] = value
def get_config(self, key):
return self.config.get(key)
# 使用示例
config1 = ConfigManager()
config2 = ConfigManager()
config1.set_config("debug", True)
print(config2.get_config("debug")) # 输出: True
2. 单例销毁与重建
class ResettableSingleton:
_instance = None
@classmethod
def get_instance(cls):
if not cls._instance:
cls._instance = cls()
return cls._instance
@classmethod
def reset_instance(cls):
cls._instance = None
class ApplicationSettings(ResettableSingleton):
def __init__(self):
self.settings = {"theme": "light"}
# 使用示例
settings1 = ApplicationSettings.get_instance()
settings1.settings["theme"] = "dark"
settings2 = ApplicationSettings.get_instance()
print(settings2.settings["theme"]) # 输出: dark
ApplicationSettings.reset_instance()
settings3 = ApplicationSettings.get_instance()
print(settings3.settings["theme"]) # 输出: light
单例模式在标准库中的应用
1. logging 模块中的单例
import logging
# logging模块本身就是单例模式的实现
logger1 = logging.getLogger("app")
logger2 = logging.getLogger("app")
print(logger1 is logger2) # 输出: True
2. None 对象是Python内置单例
a = None b = None print(a is b) # 输出: True
单例模式实践
1. 何时使用单例
-
适用场景:
-
需要控制资源访问(如数据库连接池)
-
全局配置管理
-
缓存系统
-
日志系统
-
-
不适用场景:
-
需要多实例的对象
-
测试困难的情况(单例可能导致测试相互影响)
-
2. 替代方案考虑
# 使用依赖注入替代单例
class Database:
def query(self, sql):
return f"Executing: {sql}"
class Application:
def __init__(self, db):
self.db = db
def run(self):
print(self.db.query("SELECT * FROM users"))
# 在应用顶层创建并注入单例
db = Database()
app = Application(db)
app.run()
单例模式常见问题
1. 多继承问题
class SingletonBase:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
class LoggerMixin:
def log(self, message):
print(f"LOG: {message}")
class MyClass(SingletonBase, LoggerMixin):
pass
# 使用示例
obj1 = MyClass()
obj2 = MyClass()
obj1.log("Test") # 输出: LOG: Test
print(obj1 is obj2) # 输出: True
2. 序列化与反序列化
import pickle
class SerializableSingleton:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __reduce__(self):
return (self.__class__, ())
# 使用示例
singleton1 = SerializableSingleton()
data = pickle.dumps(singleton1)
singleton2 = pickle.loads(data)
print(singleton1 is singleton2) # 输出: True
性能优化
1. 使用 __slots__ 优化单例类
class OptimizedSingleton:
__slots__ = ['data'] # 固定属性,节省内存
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
cls._instance.data = {}
return cls._instance
# 使用示例
singleton = OptimizedSingleton()
singleton.data["key"] = "value"
2. 惰性初始化
class LazySingleton:
_instance = None
def __init__(self):
if not hasattr(self, '_initialized'):
self._initialized = True
self.heavy_resource = self._init_heavy_resource()
def _init_heavy_resource(self):
# 模拟耗时初始化
import time
time.sleep(2)
return "Heavy Resource Data"
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
# 使用示例
singleton = LazySingleton() # 快速返回
# 实际使用时才初始化heavy_resource
print(singleton.heavy_resource) # 这里会耗时2秒
单例模式与设计原则
-
单一职责原则:单例类只负责自己的实例控制
-
开闭原则:对扩展开放(可继承),对修改关闭(实例化控制)
-
依赖倒置原则:客户端应依赖抽象而非具体单例实现
完整示例:配置管理器
import json
import threading
class ConfigManager(metaclass=SingletonMeta):
def __init__(self, config_file="config.json"):
self.config_file = config_file
self._lock = threading.Lock()
self._load_config()
def _load_config(self):
with self._lock:
try:
with open(self.config_file) as f:
self._config = json.load(f)
except FileNotFoundError:
self._config = {}
def get(self, key, default=None):
with self._lock:
return self._config.get(key, default)
def set(self, key, value):
with self._lock:
self._config[key] = value
with open(self.config_file, 'w') as f:
json.dump(self._config, f)
# 使用示例
config1 = ConfigManager()
config2 = ConfigManager()
config1.set("timeout", 30)
print(config2.get("timeout")) # 输出: 30
单例模式在Python中实现起来既灵活又强大,但需要谨慎使用以避免过度全局状态。根据具体需求选择合适的实现方式,可以构建出既高效又易于维护的系统架构。
更多推荐



所有评论(0)