单例
当一个类只能有一个实例,并且需要提供一个全局访问点时,就可以使用单例模式来定义类。
在Python中单例有多种定义方式,这里选取最简单的一种定义和使用修饰器的线程安全的定义方式进行举例。
首先看最简单的定义方式。
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
org = super(Singleton, cls)
cls._instance = org.__new__(cls, *args, **kwargs)
return cls._instance
class Factory(Singleton):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
obj1 = Factory("Fac1")
print(id(obj1))
obj2 = Factory("Fac2")
print(id(obj2))
最简单的定义方式定义出的单例类面临最大的问题就是线程安全,当有两个或以上的线程同时对单例类实例进行操作时,就可能会出现不可预知的潜在问题。所以使用线程安全的单例定义会更加稳妥。这里会先使用后文才会介绍到的线程,具体多线程处理的内容可参考后面的章节。
import functools
import threading
def singleton(cls):
""" 用于标记单例类的修饰器 """
cls.__new_original__ = cls.__new__
@functools.wraps(cls.__new__)
def singleton_new(cls, *args, **kw):
it = cls.__dict__.get('__it__')
if it is not None:
return it
cls.__it__ = it = cls.__new_original__(cls, *args, **kw)
it.__init_original__(*args, **kw)
return it
cls.__new__ = singleton_new
cls.__init_original__ = cls.__init__
cls.__init__ = object.__init__
return cls
def synchronized(func):
""" 为普通函数增加线程同步功能的修饰器 """
func.__lock__ = threading.Lock()
def synced_func(*args, **kwargs):
with func.__lock__:
return func(*args, **kwargs)
return synced_func
@singleton
class ProgramState:
__activated = False
def __init__(self):
self.__activated = False
@property
def activated(self):
return self.__activated
@synchronized
@activated.setter
def activated(self, value):
self.__activated = value