zoukankan      html  css  js  c++  java
  • 浅谈Python设计模式

      本篇主要介绍一下关于Python的单例模式,即让一个类对象有且只有一个实例化对象。

    一、使用__new__方法(基类)

      要实现单例模式,即为了让一个类只能实例化一个实例,那么我们可以去想:既然限制创建实例,那么我们可以修改其创建实例的根源即可,那就是父类__new__方法。

      注意:不能使用自身的__new__()方法,应为自身这个类去进行实例化,是调用父类的__new__方法,若调用自身的__new__方法,那不就死循环了么,可以参考我的另外一篇博客:python类的__new__()

    class SingleTon(object):
        def __new__(cls, *args, **kwargs):
            if not hasattr(cls, '_instance'):
                cls._instance = super().__new__(cls, *args, **kwargs)
            # return super().__new__(cls, *args, **kwargs)
            return cls._instance
    
    class Foo(SingleTon):
        pass
    
    if __name__ == '__main__':
        f1 = Foo()
        f2 = Foo()
        print('f1的id:',id(f1))
        print('f2的id:',id(f2))
    
    # f1的id: 2151027475064
    # f2的id: 2151027475064

      注释:通过修改父类的__new__方法,去干涉子类的实例化创建实例,实现只能一个类只能有一个实例的效果。

    二、使用闭包的形式

      无论怎么实现,均为了让一个类只有一个实例对象,那么我们可以当类创建一个实例,我们就把使用一个变量把该实例记录下来,若该变量已经有实例了,便可把该变量返回即可,不让其进行创建新的实例。

    def singleton(cls, *args, **kwargs):
        instances = None
        def get_instance(*args, **kwargs):
            nonlocal instances
            if instances is None:
                instances = cls(*args, **kwargs)
            return instances
        return get_instance
    
    @singleton
    class Bar(object):
        def __init__(self,name):
            self.name = name
    
    if __name__ == '__main__':
        b1 = Bar('alex')
        b2 = Bar('hello')
        print(b1.name)
        print(b2.name)

      注:为了实现单例模式,可以在类创建实例的时候对其进行限制,即通过判断该类是否已经创建了实例,若没有进行过实例化,则我们让其进行实例化,反之,返回原有对象即可。

    三、使用元类的方式

     首先我们需要明确的是,当我们使用元类时:

      1、类由type创建,创建类时,type的__init__方法自动执行,类()  --》执行type的 __call__方法(类的__new__方法,类的__init__方法)。

      2、对象由类创建,创建对象时,类的__init__方法自动执行,对象() -- 》执行类的 __call__ 方法。

     那么我们可以思考:

      当我们调用 类() 时不就是一个实例化的过程吗,就自动回执行 type中的call方法,所以我们需要去实现单例模式,只需要在call方法中对其进行限制是不是就可以达到我们想要的效果呢?试一试

    class SingleTonType(type):
    
        def __init__(self,*args, **kwargs):
            super().__init__(*args, **kwargs)
    
        def __call__(cls, *args, **kwargs):
            _instance = None  # 设置一个变量,用来存储是否创建实例
            print('cls:',cls)
            if _instance is None:
                obj = cls.__new__(cls,*args, **kwargs)  # 会一直找到能创建实例的父类,创建实例
                cls.__init__(obj, *args, **kwargs) # 构造方法去丰富该实例
                cls._instance = obj   # 并将变量修改的创建的实例
            return _instance
    
    class Foo(metaclass=SingleTonType):
        def __init__(self,name):
            self.name = name
    
    if __name__ == '__main__':
        obj1 = Foo('hello')  # 会调用type类(SingleTonType)中的call方法
        obj2 = Foo('world')

      执行结果:

    cls: <class '__main__.Foo'>
    cls: <class '__main__.Foo'>
    1841145040 1841145040

      是不是达到我们实现 -- 一个类只拥有一个实例对象的效果了呢?

      总结:其实实现单例模式,只需要在类进行实例化的时候,对其进行限制即可。比如在类进行实例化时,会调用父类的__new__方法,若使用元类,会调用call()方法,那么我们只需要在这两个方法中对其加以限制即可。

      使用修饰器闭包的利用的也是同样的原理。

  • 相关阅读:
    【求助】Oracle 新手困惑,System.Data.OracleClient requires Oracle client software version 8.1.7 or greater
    什么是APS高级计划排程(高级计划排产)一
    【求助】Html弄的比较少,问一个弱弱的问题,为什么下面代码在IE中tr之间有空白行,而在Firefox中没有空白
    使用Jmeter测试快速入门
    Jmeter数据库压测(Windows下进行压测)
    Charles安装真机证书
    Jmeter组件参数化
    Jmeter脚本录制(App)
    Jmeter的介绍
    Fiddler的使用
  • 原文地址:https://www.cnblogs.com/littlefivebolg/p/9860755.html
Copyright © 2011-2022 走看看