单例模式的意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。【1】
1.最简单的单例模式。【2】
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton,cls).__new__(cls)
return cls.instance
通过定义__new__()方法保证每次创建实例时都是同一个实例。
2.单例模式
单例模式的类应该提供一个接口让客户端获取唯一个实例。【1】
2.1懒汉式单例模式
只有需要时才去获取单例实例。
class Singleton(object):
__instance = None
def __init__(self):
if not Singleton.__instance:
print(" __init__ method called..")
else:
print("Instance alreadly created:", self.getInstance())
@classmethod
def getInstance(cls): # 全局访问点
if not cls.__instance:
cls.__instance = Singleton()
return cls.__instance
根据【1】,应该定义一个Singleton类,其构造函数应该是protected修饰的,只公开getInstance()接口,并且其唯一的实例__instance是private的,应该由Singleton的子类来实例。但是python和c++、java等不同,并没有这些修饰符。因此实现方式有所不同。
这里的代码是想让客户端不是通过实例化获取单例实例,而是通过getInstance()获取实例。因为其是类方法,因此可以直接通过类去调用,从而获取唯一的实例。同时,只有我们去调用getInstance()才会获取,因此是懒汉式的。
2.2饿汉式单例模式
在调用getInstance()前实例已经存在。从懒汉式很容易修改成饿汉式的。
3.元类实现单例模式
在python中,类的定义由它的元类决定,因此可以通过自己定义元类来定制自己所需要的类。
用__call__()阻断__new__()和__init__()。
实例化一个类的时候先调用__call__(),然后再调用__new__()和__init__()。
class MetaSingleton(type):
_instance = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instance:
cls._instance[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instance[cls]
class Logger(metaclass=MetaSingleton):
pass
logger1 = Logger()
logger2 = Logger()
print(logger1,logger2)
这里只是用元类简单实现单例模式,并没有严格按照上面第二部分要求实现。
首先我们定义一个元类MetaSingleton,继承type类。然后重写了__call__()方法。
然后我们定义一个类Logger,指定其元类是MetaSingleton。就是说类Logger是元类MetaSingleton的实例。
logger1=Logger()简单地看是实例化对象。
深层地看,在python中()是调用的语法,为什么Logger()可以调用,实际上是它的类,即元类定义了
call()方法。而在我们定义的__call__()方法中调用了父类的__call__()完成操作,即调用了type类的__call__()方法,而type类的__call__()方法实际上调用了Logger类的__new__()和__init__()方法来实现实例化的。而我们的Logger类没有重写这两个方法,因此会调用其父类object的这两个类。
4.Monostate单例模式
一个类有且只有一个对象。通常让实例共享对象相同状态,但不限制实例个数。
class Borg:
__shared_state = {"1":"2"}
def __init__(self):
self.x = 1
self.__dict__ = self.__shared_state
b = Borg()
b1 = Borg()
b.x = 4
print("Borg object 'b': ", b)
print("Borg object 'b1': ", b1)
print("Object State 'b': ", b.__dict__)
print("Object State 'b1': ", b1.__dict__)
这里b和b1是不同的实例,但它们共享相同状态__shared_state。
参考:
【1】设计模式:可复用面向对象软件的基础
【2】python设计模式第二版