单例模式确保一个类在整个程序中只有一个实例,并提供一个全局访问点。它通常用于管理共享资源,如数据库、日志系统或文件管理器。
这个例子向我们展示了类如何仅创建一个对象,并在每次被调用时返回同一个对象。
Python
CODEBLOCK_ddd329c8
Output
True
解释:
- class Single: 定义了一个名为 Single 的类,instance = None:类变量用于存储单一对象。
- def new(cls): 控制对象的创建,if cls.instance is None:检查对象是否已经存在。
- cls.instance = super().new(cls): 只创建一次对象,而 return cls.instance:总是返回同一个对象。
- a = Single(): 第一次调用创建了实例,b = Single():第二次调用重用了同一个实例。
- print(a is b): 确认两个变量指向同一个对象。
实现单例模式的方法
1. 模块级单例
默认情况下,所有 Python 模块都是单例。在模块中定义的任何变量或函数在导入时都是共享的。 例如: 在下面的例子中,Singleton.py、samplemodule1.py 和 samplemodule2.py 这三个文件共享来自 Singleton.py 的一个变量。
Python
CODEBLOCK_e73232c2
Python
CODEBLOCK_9fa6a14c
Python
CODEBLOCK_715bf36e
Output
这里,samplemodule1 修改的值也反映在了 samplemodule2 中。
!singleton终端快照
解释:
- samplemodule1 修改了 singleton.var。
- samplemodule2 反映了更新后的值,因为模块本身就是一个单例。
2. 经典单例
经典单例仅在实例不存在时才创建一个实例。否则,它返回已创建的实例。
Python
CODEBLOCK_7c639f75
Output
True
Singleton Variable
解释:
- if not hasattr(cls, ‘inst‘): 检查实例是否已存在。
- cls.inst = super().new(cls): 如果不存在则创建一个新实例。
- return cls.inst: 总是返回同一个实例。
- s1 = Singleton() 和 s2 = Singleton(): 两个变量都引用同一个实例。
子类示例: 让我们看看当单例类被子类化时会发生什么。
Python
CODEBLOCK_cb453f37
Output
> False
> Singleton Variable
解释:
- SingletonChild 继承自 SingletonClass。
- child 是 SingletonChild 的一个实例。
- 由于 SingletonClass 是单例,child 与 singleton 共享同一个实例。
- 访问 child.singlvariable 返回与 singleton.singlvariable 相同的值。
3. Borg 单例
Borg 单例允许不同的实例共享相同的状态。
Python
CODEBLOCK_026751ff
Output
False
Shared Variable
解释:
- _shared: 所有实例的共享状态字典。
- new 确保所有实例共享 _shared 状态。
- b1 和 c1: 不同的实例但共享相同的数据。
- c1 是 b1: False,实例是不同的。
- c1.val: 从 b1 访问共享状态。
重置共享状态
Borg 单例在实例之间共享状态。重置允许在保持 Borg 结构的同时,创建一个具有独立状态的新实例。
Python
CODEBLOCK_702853d1
Output
重置共享状态会删除以前的属性。现在访问 val 会导致 AttributeError。
> Traceback (most recent call last):
> File "example.py", line 12, in
> print(nb1.val)
> AttributeError: ‘NB‘ object has no attribute ‘val‘
使用经典单例构建网络爬虫
这个例子使用经典单例模式来构建一个简单的多线程应用程序。