Table of Content
单利模式(Singleton)是大部分开发任务中常用的设计模式之一。这里我主要总结一下 Python 中的单利实现方式。
我综合了许多人的意见,主要有这样几种实现方式:
-
类实例与类变量绑定。
-
共享属性。
-
使用装饰器。
-
使用元类。
类实例与类变量绑定
先来看第一种方式:
class Singleton(object):
_instance = None
def __new__(cls, *args):
if not isinstance(cls._instance, cls):
cls._instance = super(Singleton, cls).__new__(cls, *args)
return cls._instance
看起来似乎不错,但却存在一个严重的问题 —— 如果某个类继承了这个 Singleton
类,它将可以重写了父类的 __new__
方法,这样就会导致其失去唯一性。
class MyClass(Singleton):
def __new__(cls, *args):
return super(D, cls).__new__(cls, *args)
共享属性
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
使同一个类的所有实例具有相同的属性来实现单例效果。但这样做,生成的实例将是不同的对象。
使用装饰器
通过装饰器实现的方式,其实可以看做第一种方式的升级本版本。
def singleton(_cls):
insts = {}
def getinstance(*args, **kwargs):
if _cls not in insts:
insts[_cls] = _cls(*args, **kwargs)
return insts[_cls]
return getinstance
@singleton
class MyClass(object):
pass
问题显而易见,而我们也并不希望在此之外定义太多的内容。
使用元类
事实上,通过使用元类(__metaclass__
)也可以达到单例效果,并且不失为一种好方法。
class Singleton(type):
def __init__(cls, name, bases, dict):
super(Singleton, cls).__init__(name, bases, dict)
cls._instance = None
def __call__(cls, *args, **kw):
if cls._instance is None:
cls._instance = super(Singleton, cls).__call__(*args, **kw)
return cls._instance
class MyClass(object):
__metaclass__ = Singleton