单例模式是一种创建型设计模式,其目的是为了保证一个类仅有一个实例,并提供一个访问它的全局访问点,这么做有时是为了限制对共享资源的并发访问。
关于这个模式,我不打算像前面几个创建型模式逐步讲为什么使用,而是关注怎么实现单例 的目的。
单例模式的实现
单例模式有两种实现方式:
- Module-level Singleton
- Classic Singleton
Module-level Singleton
通过模块文件的方式实现,一个模块本身就是一个单例。
Modules are “singletons” in Python because import only creates a single copy of each module; subsequent imports of the same name keep returning the same module object.
首先我们的文件结构如下:
.
├── test0.py
├── test2.py
└── utils.py
在 utils.py 中的代码:
print("import utils:")
class Man:
common = {
}
def __init__(self):
self.shared = {
}
man = Man()
shared_value = "hello"
在 test0.py 中的代码:
import utils
print(utils.shared_value)
utils.shared_value += " add by test0 module"
print(id(utils))
print(id(utils.man))
在 test2.py 中的代码:
import utils
print("*"*10)
print(utils.shared_value)
print(id(utils))
print(id(utils.man))
此时在终端中调试
>>> import test0
import utils:
hello
2264080776976
2264081025424
>>> import test2
**********
hello add by test0 module
2264080776976
2264081025424
可以看到在同一个进程中, test0 和 test2 都在代码中执行过import utils,对比输出后可以得到下面的观察结果:
- 该模块只被执行一次(这可以从
import test0的输出import utils获知) - 两个代码中出现的
utils的id是一致的,这也意味着调用它们的属性也会是一致的,比如man这个Man实例 - 在
test0中执行utils.shared_value修改影响到test2中的utils.shared_value
而这就意味着我们用模块文件的形式实现了单例。
Classic Singleton
这是经典的单例实现方式,通过这种方式实现的类只会在没有其他实例存在时,才会创建一个实例,否则它只会返回已经创建的类实例。
相信大家都对 __init__ 很熟悉,但很少接触到 __new__, 而这种单例的实现就是基于这个对这个类型函数的修改。
首先要明白一个类进行实例化时会经过下面的调用流程:

最低0.47元/天 解锁文章
911

被折叠的 条评论
为什么被折叠?



