Python设计模式-单例模式

发布于:2025-04-11 ⋅ 阅读:(39) ⋅ 点赞:(0)

在这里插入图片描述

一、单例模式核心思想

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。该模式主要解决以下问题:

  • 资源控制(如数据库连接池)
  • 配置信息全局一致性
  • 避免重复创建消耗资源的对象

二、Python实现单例的5种方式

1. 模块级单例(Pythonic方式)

# singleton.py
class _Singleton:
    def __init__(self):
        self.value = None

instance = _Singleton()

# 使用方式
from singleton import instance
instance.value = "Hello"

原理: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:
    pass

优势:可复用装饰器,不影响类原有逻辑

3. __new__方法重写

class Singleton:
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

注意:需同时重写__init__避免重复初始化

4. 元类实现

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 Database(metaclass=SingletonMeta):
    pass

特点:在类创建层面控制实例化行为

5. 线程安全单例(带锁版)

from threading import Lock

class ThreadSafeSingleton:
    _instance = None
    _lock = Lock()
    
    def __new__(cls):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:  # 双重检查
                    cls._instance = super().__new__(cls)
        return cls._instance

三、单例模式深度分析

生命周期管理

  • Python的单例生命周期与模块/程序相同
  • 可通过弱引用(weakref)实现可销毁的单例

继承问题

子类化单例类时需注意:

class BaseSingleton(metaclass=SingletonMeta): pass

class ChildA(BaseSingleton): pass  # 正确
class ChildB(BaseSingleton): pass  # 与ChildA不是同一个实例

测试注意事项

  1. 使用unittest.mock.patch替换单例实例
  2. 测试间注意清理单例状态

四、实际应用场景

典型案例

  1. 日志记录器(全局统一日志配置)
  2. 数据库连接池管理
  3. 应用配置管理
  4. 设备驱动访问(如打印机)

Django中的单例实践

# settings.py 本质是模块级单例
from django.conf import settings

# middleware.py 中间件通常设计为单例
class CustomMiddleware:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.init_resources()
        return cls._instance

五、反模式与替代方案

滥用单例的坏处

  1. 隐式耦合(hidden dependencies)
  2. 测试困难
  3. 违反单一职责原则

替代方案

  1. 依赖注入(Dependency Injection)
  2. 全局变量(简单场景)
  3. 上下文管理器(资源管理场景)

六、性能优化建议

  1. 使用__slots__减少内存占用
  2. 延迟初始化(Lazy Initialization)
  3. 考虑使用functools.lru_cache实现缓存式单例
from functools import lru_cache

@lru_cache(maxsize=1)
def get_config():
    return load_config_file()

七、总结

Python实现单例的推荐选择:

  • 简单场景:模块变量
  • 需要继承:装饰器或元类
  • 多线程环境:带锁实现
  • 需要缓存功能:lru_cache

最佳实践:除非确需全局唯一实例,否则优先考虑依赖注入等更灵活的模式


网站公告

今日签到

点亮在社区的每一天
去签到