Python实现单例模式的多种方法
一些Pythonic技巧实现的单例模式
目的
单例模式可以保证一个类只有一个实例,并提供一个访问它的全局访问点。什么情况下需要一个类只能创建一个实例这种情况呢?举一些例子,操作系统只能有一个文件系统,一个窗口管理器。方法
为了实现单列模式,我们可以让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。使用
当类只能有一个实例而且调用端可以从一个公共入口访问。
作为父类,用来扩展其他只能唯一实例化的类注意
注意创建过程中的线程安全性。由于该模式需要一个静态变量来保存唯一的实例,为了线程安全需要改静态变量的线程安全。下面的实现保证线程安全采用加锁的方法。单例模式中的主动实例化和被动实例化
主动实例化指在加载主类的时候就实例化单例类,并保存到类的静态变量中,它是线程安全的。被动实例化指在首次调用单例类静态方法或构造器时创建。问题:Python可以实现主动实例化吗?
实现
下面采用两种语言实现,同时考虑线程不安全的情况。
采用类变量是保存唯一实例
1 | class Singleton: |
考虑线程安全的情况。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import threading
class Singleton:
def __new__(cls, *args, **kwargs):
with threading.Lock():
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
# 这种办法线程安全,但效率不高,没有必要一开始就加锁。可以先检查是否有实例化,
# 然后再加锁检查时候有实例化。第一次检查是为了是否需要进入加锁创建状态,第二
# 次检查是确认加锁前是否已经有现车实例化该类。
class Singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
with threading.Lock():
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
class Demo(Singleton):
spam = 1
使用元类方法
1 | class Singleton(type): |
转载请包括本文地址:https://allenwind.github.io/blog/2455
更多文章请参考:https://allenwind.github.io/blog/archives/