Python下的设计模式总结----创建型设计模式(一)
最近在学习设计模式,而开发的语言中比较中意的就是python了,在这里总结下.
设计模式一般分为三大类:构造型,结构型,行为型
先从创建型设计模式开始,创建型设计模式包括:单例模式,抽象工厂模式,工厂方法模式,生成器模式,惰性初始化模式,对象池模式,原型模式.
单例模式
单例模式的定义是:保证一个类仅有一个实例,并提供一个它的全局访问点.
先来看看14年前(没写错)的前辈介绍的单例模式例程
from __future__ import print_function class Borg: __shared_state = {} def __init__(self): self.__dict__ = self.__shared_state self.state = "Init" def __str__(self): return self.state class YourBorg(Borg): pass if __name__ == '__main__': rm1 = Borg() rm2 = Borg() rm1.state = 'Idle' rm2.state = "Running" print('rm1:{0}'.format(rm1)) print('rm2:{0}'.format(rm2)) rm2.state = 'Zombie' print('rm1:{0}'.format(rm1)) print('rm2:{0}'.format(rm2)) print('rm1 id:{0}'.format(id(rm1))) print('rm2 id:{0}'.format(id(rm2))) rm3 = YourBorg() print('rm1:{0}'.format(rm1)) print('rm2:{0}'.format(rm2)) print('rm3:{0}'.format(rm3)) # Output # rm1:Running # rm2:Running # rm1:Zombie # rm2:Zombie # rm1 id:140609170593696 # rm2 id:140609170593624 # rm1:Init # rm2:Init # rm3:Init
简单解释下,需要get的点是下面这段代码
__shared_state = {} def __init__(self): self.__dict__ = self.__shared_state self.state = "Init"
self.__dict__是对象的字典表示.将对象的属性设为全局静态变量.
根据输出结果,rm1和rm2俨然是一个实例.然而打印出来的rm1,rm2的变量id是不一致的,所以rm1,rm2并不是同一个实例.但是却有同样的状态和行为.但从结果上来看,确实实现了单例模式的要求.(虽然有种走捷径的感觉)
下面看看另一个版本的,其实就是换个形式,原理还是建多个实例,表现一致.其他部分的代码和上面的一致.
class Borg(object): __state = {} def __new__(cls, *p, **k): self = object.__new__(cls, *p, **k) self.__dict__ = cls.__state return self def __init__(self): self.state = "Init"
单例模式的创建有很多种方式.
这里有讨论链接描述
升级版,通过__metaclass__实现.这个版本中同一个id说明是同一个对象.
class Singleton(type): def __init__(self, name, bases, dict): super(Singleton, self).__init__(name, bases, dict) self._instance = None def __call__(self, *args, **kw): if self._instance is None: self._instance = super(Singleton, self).__call__(*args, **kw) return self._instance class MyClass(object): __metaclass__ = Singleton one = MyClass() two = MyClass() two.a = 3 print one.a # 3 print id(one) # 139798461922256 print id(two) # 139798461922256 print one == two # True print one is two # True
还可以通过装饰器来实现.这是第一个方法的高级版本,更pythonic,更elegant的方法.
这个例子中,单例类本身不知道自己是单例的,应为他本身(自己的代码)就不是单例的.
def singleton(cls, *args, **kw): instances = {} def _singleton(): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return _singleton @singleton class MyClass(object): a = 1 def __init__(self, x=0): self.x = x one = MyClass() two = MyClass() two.a = 3 print one.a # 3 print id(one) # 140630714076048 print id(two) # 140630714076048 print one == two # True print one is two # True one.x = 1 print one.x # 1 print two.x # 1
好东西留到最后,来个超级无敌版的
class Singleton: """ A non-thread-safe helper class to ease Implementing singletons. This should be used as a decorator -- not a metaclass -- to the class that should be singleton. The decorated class can define one `__init__` function that takes onelythe `self` argument. Other than that, there are no restrictions that apply to the decorated class. To get the singleton instances, use the `instances` method. Trying to use `__call__` will result in a `TypeError` being raised. Limitations: The decorated class cannot be inherited from. """ def __init__(self, decorated): self._decorated = decorated def instance(self): """ Return the singleton instance. Upon this first call, it creates a new instance of decorated class and calls its `__init__` method. On all subsequent calls, the already created instance is returned. """ try: return self._instance except AttributeError: self._instance = self._decorated() return self._instance def __call__(self): raise TypeError('Singletons must be accessed through `instance()`.') def __instancecheck(self, inst): return isinstance(inst, self._decorated) @Singleton class Foo: def __init__(self): print "Foo created" # f = Foo() # TypeError: Singletons must be accessed through `instance()`. f = Foo.instance() g = Foo.instance() # Foo created print f is g # True
关于python的单例模式,各家说法不一.可以根据不同的需求,使用不同的方式,适合的才是最好的.
参考文字:
https://zh.wikipedia.org/wiki/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F_(%E8%AE%A1%E7%AE%97%E6%9C%BA)
http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/
http://code.activestate.com/recipes/66531/
http://blog.csdn.net/ghostfromheaven/article/details/7671853