预约成功
一、单例模式实现方式——单例模式
单例模式(Singleton Pattern)是最常用的一种设计模式,是一种非常常用的创建型设计模式。什么场景会用到单例模式呢?就是在系统工程中只想创建单个实例对象,比如数据库连接池,Redis连接池,服务监控中心等。这个场景下,如果存在多个实例对象,那么会有无法预测的异常。同时,在设计单例模式时,需要考虑的很重要的因素就是并发性,即多线程调用时是否会存在多个线程。那么,如何设计使用单例模式呢?
二、单例模式实现方式——经典单例模式
最经典的单例模式实现非常简单,主要是:先判断类是否有这个实例,如果没有该实例,则生成一个实例;如果已经存在了一个实例,那么提供这个实例。算法代码如下:
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
s = Singleton()
print("Object Created", s)
t = Singleton()
print("Object Created", t)
运行如下代码,得到如下结果:
Object Created <__main__.Singleton object at 0x0000000001F28278>
Object Created <__main__.Singleton object at 0x0000000001F28278>
由此可见,s和t为同一个实例,即Singleton类实现了单例模式。
三、单例模式实现方式——多线程单例模式
上述代码实现了单例模式,但是是否支持多线程呢?我们可以做个测试:
import threading
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
def task(arg):
obj = Singleton()
print("Object Created", obj)
for i in range(5):
t = threading.Thread(target=task,args=[i,])
t.start()
运行结果如下:
Object Created <__main__.Singleton object at 0x0000000001EE0E48>
Object Created <__main__.Singleton object at 0x0000000001EE0E48>
Object Created <__main__.Singleton object at 0x0000000001EE0E48>
Object Created <__main__.Singleton object at 0x0000000001EE0E48>
Object Created <__main__.Singleton object at 0x0000000001EE0E48>
似乎是没有问题的。实际呢?这是因为初始化生成对象的时间比较短,如果生成对象的时间比较长呢?我们应用sleep函数来模拟这种场景。代码如下:
import threading
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls,'_instance'):
import time
time.sleep(1)
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
def task(arg):
obj = Singleton()
print("Object Created", obj)
for i in range(5):
t = threading.Thread(target=task,args=[i,])
t.start()
运行后的结果呢?我们可以看到产生了不同的对象:
Object Created <__main__.Singleton object at 0x0000000002548C18>
Object Created <__main__.Singleton object at 0x000000000260DF98>
Object Created <__main__.Singleton object at 0x0000000002550470>
Object Created <__main__.Singleton object at 0x0000000002550EF0>
Object Created <__main__.Singleton object at 0x000000000255F3C8>
也就是说,这种单例模式在多线程下是失效的,我们需要改进实现方式。那么,在多线程下如何实现单例模式呢?最经典的方式,就是加锁。多线程下单例模式的实现如下:
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __new__(cls, *args, **kw):
with Singleton._instance_lock:
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
我们可以再次测试一下,如果初始化实例时间比较长的情况下,是否会产生多个实例。测试代码如下:
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __new__(cls, *args, **kw):
with Singleton._instance_lock:
if not hasattr(cls,'_instance'):
import time
time.sleep(1)
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
def task(arg):
obj = Singleton()
print("Object Created", obj)
for i in range(5):
t = threading.Thread(target=task,args=[i,])
t.start()
运行结果如下:
Object Created <__main__.Singleton object at 0x0000000001EC8C50>
Object Created <__main__.Singleton object at 0x0000000001EC8C50>
Object Created <__main__.Singleton object at 0x0000000001EC8C50>
Object Created <__main__.Singleton object at 0x0000000001EC8C50>
Object Created <__main__.Singleton object at 0x0000000001EC8C50>
由此可以看出,确实只生成了单个实例,well done。
四、单例模式实现方式——运用元类实现单例模式
元类,是一个类的类,所以,该类是元类的实例。在Python中,一切都为对象,那么,对象都会有类型。看一下如下代码:
a = 'Hello, World'print(type(a))print(type(type(a)))
那么,这表明,str类型的元类是type,即str是type类型的一个类。
元类可以控制类创建和对象的实例化,所以可以用于创建单例。Python代码实现如下(已经加入了锁来实现多线程):
import threading
class MetaSingleton(type):
_instances = {}
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
with MetaSingleton._instance_lock:
if cls not in cls._instances:
cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Singleton(metaclass=MetaSingleton):
pass
五、单例模式实现方式——运用模块实现单例模式
默认情况下,Python中所有的模块都是单例模式,这是由于Python中的导入行为所决定的。Python中运用模块导入主要做了以下工作:
1、判断该模块是否导入;
2、如果模块已经导入,则返回模块的对象;否则,如果没有导入,则导入并实例化。
Python实现如下:
# singleton.pyclass Singleton(object): def fun(self): passobj = Singleton()
在使用时,可以按照如下方式使用:
from singleton.Singleton import obj
小结
本文介绍了三种单例模式的实现方式,其中Python中的模块都是单例,这也是实现单例模式最简单的方式,另外,本文介绍了通过__new__以及元类实现单例模式的方法,在实现的过程中,考虑了多线程。
以上就是单例模式实现方式。可能在刚讲解完这一实际应用之后,大家的印象还很模糊,不如打开电脑,那正好现在就上手操作一下,试一试吧!也许你还会发现更多python应用为您带来的乐趣环球网校的小编在这里希望这些信息可以对您有所帮助。