单例模式(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秒

单例模式与设计原则

  1. 单一职责原则:单例类只负责自己的实例控制

  2. 开闭原则:对扩展开放(可继承),对修改关闭(实例化控制)

  3. 依赖倒置原则:客户端应依赖抽象而非具体单例实现

完整示例:配置管理器

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中实现起来既灵活又强大,但需要谨慎使用以避免过度全局状态。根据具体需求选择合适的实现方式,可以构建出既高效又易于维护的系统架构。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐