Python单例模式(Singleton)的N种实现

2020-06-19 00:00:00 模式 方法 实例 装饰 创造

很多初学者喜欢用全局变量,因为这比函数的参数传来传去更容易让人理解。确实在很多场景下用全局变量很方便。不过如果代码规模增大,并且有多个文件的时候,全局变量就会变得比较混乱。你可能不知道在哪个文件中定义了相同类型甚至重名的全局变量,也不知道这个变量在程序的某个地方被做了怎样的操作。

因此对于这种情况,有种更好的实现方式:
单例(Singleton)

单例是一种设计模式,应用该模式的类只会生成一个实例。

单例模式保证了在程序的不同位置都可以且仅可以取到同一个对象实例:如果实例不存在,会创建一个实例;如果已存在就会返回这个实例。因为单例是一个类,所以你也可以为其提供相应的操作方法,以便于对这个实例进行管理。

举个例子来说,比如你开发一款游戏软件,游戏中需要有“场景管理器”这样一种东西,用来管理游戏场景的切换、资源载入、网络连接等等任务。这个管理器需要有多种方法和属性,在代码中很多地方会被调用,且被调用的必须是同一个管理器,否则既容易产生冲突,也会浪费资源。这种情况下,单例模式就是一个很好的实现方法。

单例模式广泛应用于各种开发场景,对于开发者而言是必须掌握的知识点,同时在很多面试中,也是常见问题。本篇文章总结了目前主流的实现单例模式的方法供读者参考。

希望看过此文的同学,在以后被面到此问题时,能直接皮一下面试官,“我会 4 种单例模式实现,你想听哪一种?”

以下是实现方法索引:

  • 使用函数装饰器实现单例
  • 使用类装饰器实现单例
  • 使用 __new__ 关键字实现单例
  • 使用 metaclass 实现单例

使用函数装饰器实现单例

以下是实现代码:

def singleton(cls):
    _instance = {}

    def inner():
        if cls not in _instance:
            _instance[cls] = cls()
        return _instance[cls]
    return inner
    
@singleton
class Cls(object):
    def __init__(self):
        pass

cls1 = Cls()
cls2 = Cls()
print(id(cls1) == id(cls2))

相关文章