第五章:单例模式

2020-08-19  本文已影响0人  Benedict清水

一、什么是单例模式

故事:你是我的唯一
假期总是短暂的,李力和女朋友要分开了。在车站的站台上,李力深情的看着女朋友说,“你是我此生的唯一”

1.1用程序模拟生活

我们都希望爱情里我们是彼此的唯一,程序如人生,有些类我们也希望它只有一个实例。

class MyBeautifulGril:
    __instance = None
    __isFirstInit = False

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            MyBeautifulGril.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self, name):
        if not self.__isFirstInit:
            self.__name = name
            print("遇见" + name + ", 我一见钟情!")
            MyBeautifulGril.__isFirstInit = True
        else:
            print("遇见" + name + ", 我置若惘闻!")

    def showMyHeart(self):
        print(self.__name + "就是我心中的唯一!")


def TestLove():
    jenny = MyBeautifulGril("Jenny")
    jenny.showMyHeart()
    kimi = MyBeautifulGril("kimi")
    kimi.showMyHeart()
    print("id(jenny):", id(jenny), "id(kimi):", id(kimi))


if __name__ == "__main__":
    TestLove()

输出结果:

遇见Jenny, 我一见钟情!
Jenny就是我心中的唯一!
遇见kimi, 我置若惘闻!
Jenny就是我心中的唯一!
id(jenny): 4326687312 id(kimi): 4326687312

二、单例模式的定义

2.1定义

确保一个类只有一个实例,并且提供一个访问它的全局方法。

单例模式就是保证一个类有且只有一个对象(实例)的一种机制。单例模式用来控制某些事物只允许有一个个体。

三、单例模式的模型抽象

3.1单例模式的实现方式有很多种,下面列出几种常见的方式。

(1)、重写__new__和__init__方法

class Singleton1:
    """单例模式实现方式"""
    __instance = None
    __isFirstInit = None

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            Singleton1.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self, name):
        if not self.__isFirstInit:
            self.__name = name
            Singleton1.__isFirstInit = True

    def getName(self):
        return self.__name


def testfunc():
    tony = Singleton1("Tony")
    karry = Singleton1("Karry")
    print(tony.getName(), karry.getName())
    print("id(tony):", id(tony), "id(karry):", id(karry))
    print("tony is karry:", tony is karry)


if __name__ == "__main__":
    testfunc()

输出结果:

Tony Tony
id(tony): 4351308368 id(karry): 4351308368
tony is karry: True

在Python3的类中,__new__负责对象的创建,而__init__负责对象的初始化:__new__是一个类方法,而__init__是一个对象方法。
__new__是我们通过类名进行实例化对象时自动调用的,__init__是在每一次实例化对象后调用的,__new__方法创建一个实例之后返回这个实例的对象,并将其传递给__init__方法的self参数。
在上面的实例代码中,当调用__new__时,我们会传递类对象给cls参数,我们定义一个静态的__instance类变量,用来存放Singleton1的对象,__new__方法每次返回同一个__instance对象(若未初始化,则进行初始化)。因为每一次通过s= Singleton1()的方式创建对象时,都会自动调用__init__方法来初始化实例对象,因此__isFirstInit的作用就是确保只对__instance对象进行一次初始化。
(2)、自定义metaclass的方法

class Singleton2(type):
    """单例模式实现方式二"""

    def __init__(cls, what, bases=None, dict=None):
        super().__init__(what, bases, dict)
        cls.__instance = None  # 初始化全局变量cls.__instance为None

    def __call__(cls, *args, **kwargs):
        """控制对象的创建过程,如果cls.__instance为None,则创建,否则直接返回"""
        if cls.__instance is None:
            cls.__instance = super().__call__(*args, **kwargs)
        return cls.__instance


class CustomClass(metaclass=Singleton2):
    """用户自定义的类"""

    def __init__(self, name):
        self.__name = None

    def getName(self):
        return self.__name


if __name__ == "__main__":
    tony = CustomClass("Tony")
    karry = CustomClass("karry")
    print(tony.getName(), karry.getName())
    print("id(tony):", id(tony), "id(karry):", id(karry))
    print("tony == karry:", tony == karry)

输出结果:

Tony Tony
id(tony): 4507292144 id(karry): 4507292144
tony == karry: True

(3)、装饰器的方法

def singletonDecorator(cls, *args, **kwargs):
    """定义一个单例装饰器"""
    instance = {}

    def wrapperSingleton(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return wrapperSingleton


@singletonDecorator
class Singleton3:
    """使用单例装饰器修饰一个类"""

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name


if __name__ == "__main__":
    tony = Singleton3("Tony")
    karry = Singleton3("karry")
    print(tony.getName(), karry.getName())
    print("id(tony):", id(tony), "id(karry):", id(karry))
    print("tony == karry:", tony == karry)

输出结果:

Tony Tony
id(tony): 4313830736 id(karry): 4313830736
tony == karry: True

装饰器的实质就是对传进来的参数进行补充,可以在不对原有的类做任何代码变动的前提下增加额外的功能,使用装饰器可以装饰多个类。用装饰器的方式来实现单例模式,通用性非常高,在实际项目中用的非常多。

四、基于框架的实现

4.1基于上面的方式三装饰器的方式实现单例模式
from singleton3 import singletonDecorator


@singletonDecorator
class MyBeautifulGril:

    def __init__(self, name):
        self.__name = name
        if self.__name == name:
            print("遇见" + name + ", 我一见钟情!")
        else:
            print("遇见" + name + ", 我置若罔闻!")

    def showMyHeart(self):
        print(self.__name + "就是我心中的唯一!")

def TestLove():
    jenny = MyBeautifulGril("Jenny")
    jenny.showMyHeart()
    kimi = MyBeautifulGril("kimi")
    kimi.showMyHeart()
    print("id(jenny):", id(jenny), "id(kimi):", id(kimi))


if __name__ == "__main__":
    TestLove()

输出结果:

遇见Jenny, 我一见钟情!
Jenny就是我心中的唯一!
Jenny就是我心中的唯一!
id(jenny): 4414658400 id(kimi): 4414658400

4.2 应用场景

(1)确保一个类有且只有一个实例
(2)项目中的一些全局管理类(Manager)可以用单例模式来实现。

上一篇下一篇

猜你喜欢

热点阅读