美文网首页
第五章:单例模式

第五章:单例模式

作者: Benedict清水 | 来源:发表于2020-08-19 14:22 被阅读0次

    一、什么是单例模式

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

    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)可以用单例模式来实现。

    相关文章

      网友评论

          本文标题:第五章:单例模式

          本文链接:https://www.haomeiwen.com/subject/jxrhjktx.html