单例模式

何为单例模式?

单例模式是一种设计模式, 表示针对某类的实例, 有且仅会有单个实例对象会被创建, 这样, 进程在运行过程中, 在任何地方得到的这个类的实例总是共享的

应用场景

比如redis的连接实例, 数据库的连接实例等等, 在进程运行过程中, 我们不希望多次创建连接实例, 这时就可以使用单例

单例实现

那么, 在python里如何创建单例呢

在类实例前, 会调用一个内置的函数__new__, 我们可以通过修改这个函数, 来保证实例化的结果总是同一个实例

__new__ 实现单例

class S(object):
    def __new__(cls):
        if hasattr(cls, 'ins'):
            return getattr(cls, 'ins')
        instance = object.__new__(cls)
        cls.ins = instance
        return instance

if __name__ == '__main__':
    s1 = S()
    s2 = S()

    print(id(s1))
    print(id(s2))

这里我们运行后, 可以看大id(s1)id(s2)的结果是一样的, 说明两次实例化返回的是相同的实例

静态方法调用

在PHP里, 可以通过静态类方法调用得到单例, 在python里也可以这么做

class S(object):
    @classmethod
    def get_ins(cls):
        if hasattr(cls, 'ins'):
            return cls.ins
        cls.ins = cls()
        return cls.ins

if __name__ == '__main__':
    s1 = S.get_ins()
    s2 = S.get_ins()

    print(id(s1)) # 4517777872
    print(id(s2)) # 4517777872

这里我们得到的也是id(s1)id(s2)一样的, 也能得到单例

模块引入方式

我们知道在python在引入模块的变量时, 只会引入一次, 基于这个特性, 我们也可以实现单例

s.py 模块中

class A(object):
    pass

a = A()

ins.py 模块中

import s

a1 = s.a
a2 = s.a

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

可以看到, 得到的也是相同的实例

right