• Python设计模式之单例模式


    单例模式

    单例模式需要注意的地方在于

    • 如何保证创建的实例是唯一的
    • 如何保证多线程情况下的访问
    • 清晰明了

    目前有这么几种方法:

    1. module
    2. metaclass
    3. __new__
    4. decorator

    module

    其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

    1. 首先在一个py文件中定义这么一个单例类:

      class Singleton(object):
          def __init__(self):
              self._val = 10
          @property
          def val(self):
              return self._val
          @val.setter
          def val(self, val):
              self._val = val
      singleton = Singleton()
      
    2. 然后再在其它的文件中import

      from Singleton import singleton
      assert singleton.val == 10
      singleton.val = 20
      assert singleton.val == 20
      

    但是这个有个缺点,就是程序一开始的时候就进行了创建,造成不必要的浪费,最好是在使用的时候才进行创建,还有另外一个缺点在于,如果有人不遵守规定使用已经创建好的实例,而是自己创建则无法实现单例。

    metaclass

    这正是元类可以做的事情-通过声明一个元类,我们告诉Python把类对象的创建路由到我们提供的另一个类,从而达到拦截类的创建的目的。用户唯一需要做的是,它们需要声明元类,每个这么做的都会自动获取到元类所提供的扩展。

    class Singleton(type):
        def __init__(cls, what, bases, dict):
            super().__init__(what, bases, dict)
            cls._instance = None
        def __call__(cls, *args, **kwargs):
            if cls._instance is None:
                cls._instance = super().__call__(*args, **kwargs)
            return cls._instance
    class MyClass(metaclass=Singleton):
        pass
    class1 = MyClass()
    class2 = MyClass()
    assert class1 == class2
    

    __new__

    如果在子类中如果没有重载__new__方法,那么子类则会顺着继承关系,找到父类中的__new__,但是如果子类已经重载了,而且没有显式的调用父类的方法,那么就相当于再次进行重载,就不会再去调用父类的__new__方法,需要注意!

    class Singleton(object):
        _instance = None
        def __new__(cls, *args, **kw):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
            return cls._instance
    class MyClass(Singleton):
        pass
    class1 = MyClass()
    class2 = MyClass()
    assert id(class1) == id(class2)
    

    装饰器

    在装饰器中,我们通过拦截它的__new__实现,判断它是否存在于该类的__dict__字典中,如果存在则返回,不存在则创建该类并且存放于__dict__中,并且进行相应的初始化。

    def singleton(cls, *args, **kw):
        instances = {}
        def getinstance():
            if cls not in instances:
                instances[cls] = cls(*args, **kw)
            return instances[cls]
        return getinstance
    @singleton
    class myclass:
        pass
    class1 = myclass()
    class2 = myclass()
    assert class1 == class2
  • 相关阅读:
    DIOCP开源项目详解编码器和解码器和如何在传输中加入压缩和解压功能
    DIOCP开源项目DEMO(怎么样操作远程数据库)
    网站文件更新工具
    使用Javascript正则表达式来格式化XML内容
    加载有命名空间,但没有声名的XML
    使用参数化和块语句来提高批处理SQL语句的执行效率
    让Dotnet识别Java发送来的自定义SoapHeader
    中行的EToken
    异步调用方法时异常的捕获
    使用参数化和块语句来提高批处理SQL语句的执行效率(2)
  • 原文地址:https://www.cnblogs.com/George1994/p/7106748.html
Copyright © 2020-2023  润新知