Python中的单例设计模式

单例模式

在实际开发中,我们可能编写的类,虽然被调用(或实例化)多次,但是我们希望所实例化出来的对象都是同一个对象,即所占用的内存空间是同一块内存空间,那就需要使用到单例模式。

比如在音乐播放器软件中,我们一次只能播放一首歌,在打印机程序中,打印机一次只能有一份文档被打印。这些都需要用到单例设计模式。

那么单例模式如何设计呢?

在Python类的初始化过程中,一共分为两个步骤:

  1. 调用__new__方法分配内存空间,并返回内存空间的引用
  2. 调用__init__方法,在分配的内存空间中初始化对象

下面通过一段代码来看看类的实例化过程

class ClassInit(Object):
    def __new__(cls, *args, **kwargs):
        print("分配空间")
        instance = super().__new__(cls)
        return instance

    def __init__(self):
        print("我是初始化方法")

if __name__ == '__main__':
    ci1 = ClassInit()
    print(ci1)
    ci2 = ClassInit()
    print(ci2)
# ___________________执行结果如下:______________________
分配空间
我是初始化方法
<__main__.ClassInit object at 0x10131da50>
分配空间
我是初始化方法
<__main__.ClassInit object at 0x10131db70>

在上面的例子中,我们重写了父类的__new__方法,并调用了父类的__new__方法返回了一个实例对象,后面再调用__init__方法,进行类的实例化。在上例的第11-14行,我们还可以看出,我们创建了2个类的实例,打印出来类实例的内存地址也是不同的,也就是说上面的方法,就不是单例模式。

在上面的例子中,如果我们注释了第4行和第5行,那么返回的结果将如下:

分配空间
None
分配空间
None

我们重写了父类的__new__方法,只打印了分配空间四个字,但是调用父类的__new__方法,那么将无法分配内存空间,导致后面类无法初始化,所以打印类也就是None

通过对上面例子的理解,我们知道了,在类的初始化过程中,Python编译器会自动调用__new__方法,进行内存空间的分配,那么我们就顺着这个思路考虑,我们可以判断,当这个内存空间(实例对象)已经存在时,我们是不是就可以不用再次创建新的实例,从而达到单例模式的效果?

我们可以定义一个类属性,初始值为None,当调用__new__方法时,我们先判断这个类属性是否为None,不为None,我们才分配内存空间。请看下面的例子:

class ClassInit:
    instance = None
    def __new__(cls, *args, **kwargs):
        print("分配空间")
        if cls.instance is None:
            cls.instance = super().__new__(cls)
        return cls.instance

    def __init__(self):
        print("我是初始化方法")

if __name__ == '__main__':
    ci1 = ClassInit()
    print(ci1)
    ci2 = ClassInit()
    print(ci2)
# ___________________执行结果如下:______________________
分配空间
我是初始化方法
<__main__.ClassInit object at 0x10b6e1a90>
分配空间
我是初始化方法
<__main__.ClassInit object at 0x10b6e1a90>

第2行,定义一个类属性instance 并赋初始值为None

第5行,判断类属性instance是否为None,如果为None则调用父类的__new__方法,分配内存空间,并将内存空间的引用赋值给类属性instance。

第7行,最后返回类属性。即分配的内存空间的引用

最后看执行结果,我们调用了两次类的实例化,但是打印出来的两个类的实例化对象的内存空间地址是相同的,即它俩是类同一个实例。这样就达到了单例模式的设计需求。

你可能感兴趣的:(python)