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

http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python/31887#31887

相关推荐