Singleton Design Pattern In Python

Singleton模式是一个很有用,但被很多人 诟病的设计模式。这里不讨论它的缺点, 而仅仅讨论一下如何在 Python 中实现 Singleton 模式。

module加function

Staale认为仅仅用module加function就可以达到目的了。这个方法在SO上得到了 大多数人的支持。

in a.py:

get_foo():
    print 'getting foo ...'
    return 'bar'
foo = get_foo()

in others.py:

import a
print a.foo

我就要经典的Singleton模式!

好吧,好吧。经典的来了。

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None

    def __call__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls.instance

class A(object):
    __metaclass__ = Singleton

if __name__ == '__main__':
    a1 = A()
    a2 = A()
    print id(a1) == id(a2)

这个方法有一个小问题,它不能通过 deepcopy 的测试:

from copy import deepcopy
a3 = A()
a4 = deepcopy(a3)
print id(a3) == id(a4)

经典版本2

也可以通过重写 __new__ 方法来实现相同的目的。并且没有 deepcopy 的问题

class A(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(A, cls).__new__(cls, *args, **kwargs)
        return cls._instance

Borg模式

Singleton模式强调的是一个类只能实例化一次,但我们目的只是让实例的状态 唯一就行了,不用管它被实例化多少次。 Google员工、Python大牛Alex Martelli写了一个Borg设计模式 被很多人认为可以在Python中替代Singleton模式。

class Borg(object):
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state

if __name__ == '__main__':
    b1 = Borg()
    b2 = Borg()
    b1.name = 'hi'
    print b1.name, b2.name

    b2.age = 20
    b3 = Borg()
    print b1.age, b2.age, b3.age

Result:

hi hi
20 20 20

选择哪个?

我觉得用哪个问题都不大,看个人口味了。Django用到了Borg模式