基于Python学习《Head First设计模式》第五章 单件模式

单件模式

初步示例

创建实例前先判断是否已创建,已有就直接返回,没有才创建

实现方式

类加载时创建(推荐)

python 复制代码
# singleton.py
class Singleton:
    def __init__(self):
        self.value = "实例数据"

_instance = Singleton()  # 模块加载时创建实例

def get_instance():
    return _instance

# 使用
from singleton import get_instance
obj1 = get_instance()
obj2 = get_instance()
print(obj1 is obj2)  # True

优点:简单、线程安全、符合Python风格。

缺点:实例在导入时立即创建(非懒加载)。

重写__new__方法

python 复制代码
class Singleton:
    _instance = None

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

    def __init__(self):
        self.value = "初始化数据"

# 使用
obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)  # True
双重检查加锁
python 复制代码
import threading

class Singleton:
    _instance = None
    _lock = threading.Lock()  # 类似 Java 的 synchronized 锁
    
    def __new__(cls):
        # 第一次检查(无锁)
        if not cls._instance:
            # 获取锁(类似 synchronized 块)
            with cls._lock:
                # 第二次检查(有锁)
                if not cls._instance:
                    print("创建新实例")
                    cls._instance = super().__new__(cls)
                    # 在这里进行初始化操作
                    cls._instance.value = "初始化数据"
        return cls._instance

    def get_value(self):
        return self.value

# 创建多个线程
threads = []
for i in range(5):
    t = threading.Thread(target=Singleton(), name=f"Thread-{i+1}")
    threads.append(t)
    t.start()

# 等待所有线程完成
for t in threads:
    t.join()

使用类装饰器

python 复制代码
import functools

def singleton(cls):
    _instances = {}
    
    @functools.wraps
    def wrapper(*args, **kwargs):
        if cls not in _instances:
            _instances[cls] = cls(*args, **kwargs)
        return _instances[cls]
    return wrapper

@singleton
class MyClass:
    def __init__(self, name):
        self.name = name

# 使用
a = MyClass("Alice")
b = MyClass("Bob")
print(a.name, b.name)  # Alice Alice
print(a is b)  # True

使用元类

python 复制代码
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 Logger(metaclass=SingletonMeta):
    def __init__(self, log_file):
        self.log_file = log_file

# 使用
logger1 = Logger("app.log")
logger2 = Logger("new.log")
print(logger1.log_file)  # app.log
print(logger1 is logger2)  # True

要点总结

相关推荐
BD_Marathon9 分钟前
七大设计原则介绍
设计模式
摘星编程11 分钟前
深入理解CANN ops-nn BatchNormalization算子:训练加速的关键技术
python
魔芋红茶12 分钟前
Python 项目版本控制
开发语言·python
lili-felicity19 分钟前
CANN批处理优化技巧:从动态批处理到流水线并行
人工智能·python
一个有梦有戏的人21 分钟前
Python3基础:进阶基础,筑牢编程底层能力
后端·python
YCY^v^21 分钟前
JeecgBoot 项目运行指南
java·学习
云小逸27 分钟前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
摘星编程38 分钟前
解析CANN ops-nn中的Transpose算子:张量维度变换的高效实现
python
Liekkas Kono1 小时前
RapidOCR Python 贡献指南
开发语言·python·rapidocr
玄同7651 小时前
Python 后端三剑客:FastAPI/Flask/Django 对比与 LLM 开发选型指南
人工智能·python·机器学习·自然语言处理·django·flask·fastapi