You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.9 KiB
162 lines
4.9 KiB
"""
|
|
单例模式 (Singleton Pattern)
|
|
|
|
意图:确保一个类只有一个实例,并提供一个全局访问点。
|
|
|
|
应用场景:
|
|
- 资源管理器(如数据库连接池、线程池)
|
|
- 配置管理器
|
|
- 日志记录器
|
|
- 全局计数器
|
|
|
|
本实现提供了三种常见的单例模式实现方式:
|
|
1. 懒汉式 (延迟初始化)
|
|
2. 饿汉式 (立即初始化)
|
|
3. 线程安全的懒汉式 (使用双重检查锁定)
|
|
"""
|
|
|
|
|
|
class LazySingleton:
|
|
"""懒汉式单例 - 延迟初始化,非线程安全"""
|
|
_instance = None
|
|
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super(LazySingleton, cls).__new__(cls)
|
|
# 初始化代码
|
|
cls._instance.data = "Lazy Singleton Data"
|
|
return cls._instance
|
|
|
|
def do_something(self):
|
|
"""演示单例的功能方法"""
|
|
return f"{self.__class__.__name__} is doing something with {self.data}"
|
|
|
|
|
|
class EagerSingleton:
|
|
"""饿汉式单例 - 立即初始化,线程安全"""
|
|
_instance = None
|
|
|
|
# 在类加载时就创建实例
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super(EagerSingleton, cls).__new__(cls)
|
|
# 初始化代码
|
|
cls._instance.data = "Eager Singleton Data"
|
|
return cls._instance
|
|
|
|
def do_something(self):
|
|
"""演示单例的功能方法"""
|
|
return f"{self.__class__.__name__} is doing something with {self.data}"
|
|
|
|
|
|
import threading
|
|
|
|
class ThreadSafeSingleton:
|
|
"""线程安全的懒汉式单例 - 使用双重检查锁定模式"""
|
|
_instance = None
|
|
_lock = threading.RLock() # 使用可重入锁
|
|
|
|
def __new__(cls):
|
|
# 第一次检查,避免不必要的锁
|
|
if cls._instance is None:
|
|
# 获取锁
|
|
with cls._lock:
|
|
# 第二次检查,确保在等待锁的过程中没有其他线程创建实例
|
|
if cls._instance is None:
|
|
cls._instance = super(ThreadSafeSingleton, cls).__new__(cls)
|
|
# 初始化代码
|
|
cls._instance.data = "Thread Safe Singleton Data"
|
|
return cls._instance
|
|
|
|
def do_something(self):
|
|
"""演示单例的功能方法"""
|
|
return f"{self.__class__.__name__} is doing something with {self.data}"
|
|
|
|
|
|
class Singleton:
|
|
"""使用元类实现的单例模式"""
|
|
_instance = None
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
if cls._instance is None:
|
|
cls._instance = super(Singleton, cls).__new__(cls)
|
|
return cls._instance
|
|
|
|
def __init__(self, data=None):
|
|
# 仅在第一次初始化时设置属性
|
|
if not hasattr(self, 'initialized'):
|
|
self.data = data or "Default Singleton Data"
|
|
self.initialized = True
|
|
|
|
def do_something(self):
|
|
"""演示单例的功能方法"""
|
|
return f"{self.__class__.__name__} is doing something with {self.data}"
|
|
|
|
|
|
def test_thread_safety():
|
|
"""测试线程安全性"""
|
|
instances = []
|
|
|
|
def create_instance():
|
|
instances.append(ThreadSafeSingleton())
|
|
|
|
# 创建多个线程同时实例化
|
|
threads = []
|
|
for _ in range(10):
|
|
thread = threading.Thread(target=create_instance)
|
|
threads.append(thread)
|
|
thread.start()
|
|
|
|
# 等待所有线程完成
|
|
for thread in threads:
|
|
thread.join()
|
|
|
|
# 验证所有实例都是同一个对象
|
|
first_id = id(instances[0])
|
|
for instance in instances[1:]:
|
|
assert id(instance) == first_id, "线程安全测试失败:创建了多个实例"
|
|
|
|
print("线程安全测试通过:所有线程创建的是同一个实例")
|
|
|
|
|
|
def main():
|
|
"""演示各种单例实现"""
|
|
print("=== 单例模式演示 ===")
|
|
|
|
# 测试懒汉式单例
|
|
print("\n1. 懒汉式单例测试:")
|
|
s1 = LazySingleton()
|
|
s2 = LazySingleton()
|
|
print(f"s1 id: {id(s1)}, s2 id: {id(s2)}")
|
|
print(f"s1 == s2: {s1 is s2}")
|
|
print(s1.do_something())
|
|
|
|
# 测试饿汉式单例
|
|
print("\n2. 饿汉式单例测试:")
|
|
s3 = EagerSingleton()
|
|
s4 = EagerSingleton()
|
|
print(f"s3 id: {id(s3)}, s4 id: {id(s4)}")
|
|
print(f"s3 == s4: {s3 is s4}")
|
|
print(s3.do_something())
|
|
|
|
# 测试线程安全的懒汉式单例
|
|
print("\n3. 线程安全单例测试:")
|
|
test_thread_safety()
|
|
s5 = ThreadSafeSingleton()
|
|
s6 = ThreadSafeSingleton()
|
|
print(f"s5 id: {id(s5)}, s6 id: {id(s6)}")
|
|
print(f"s5 == s6: {s5 is s6}")
|
|
print(s5.do_something())
|
|
|
|
# 测试使用元类的单例
|
|
print("\n4. 元类单例测试:")
|
|
s7 = Singleton("Custom Data")
|
|
s8 = Singleton("This should not change") # 第二次初始化不会改变数据
|
|
print(f"s7 id: {id(s7)}, s8 id: {id(s8)}")
|
|
print(f"s7 == s8: {s7 is s8}")
|
|
print(f"s7.data: {s7.data}") # 应该是 "Custom Data"
|
|
print(s7.do_something())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |