美文网首页Python知识锦集
Python 面向对象7: 单例模式

Python 面向对象7: 单例模式

作者: IIronMan | 来源:发表于2018-11-16 18:22 被阅读2次

    一、内容

    • 1.1、单例设计模式
    • 1.2、__new__方法
    • 1.3、Python 中的单例

    二、单例设计模式

    • 2.1、设计模式

      • 设计模式前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案
      • 使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
    • 2.2、单例设计模式

      • 目的 —— 让 创建的对象,在系统中 只有 唯一的一个实例
      • 每一次执行 类名() 返回的对象,内存地址是相同的
    • 2.3、单例设计模式的应用场景

      音乐播放 对象,回收站 对象,打印机 对象

    三、__new__ 方法

    • 3.1、使用 类名() 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间,如果是 类对象的调用是不是走__new__ 方法的

    • 3.2、__new__ 是一个 由 object 基类提供的 内置的静态方法,主要作用有两个:

      • (1) 在内存中为对象 分配空间
      • (2) 返回 对象的引用
    • 3.3、Python 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给 __init__ 方法

    • 3.4、重写 __new__方法 的注意事项

      • 重写 __new__方法 一定要 return super().new(cls)
      • 否则 Python 的解释器 得不到 分配了空间的 对象引用,就不会调用对象的初始化方法
      • 注意:__new__ 是一个静态方法,在调用时需要 主动传递 cls参数
    • 3.5、如下代码(使用 类名() 创建对象时,Python 的解释器 首先 会 调用 new 方法为对象 分配空间)

      class MusicPlayer(object):
      
           def __new__(cls, *args, **kwargs):
                 # 1、创建对象时候,__new__方法会被自动调用
                 # 2、如果不返回任何结果,下面的__init__初始化方法是不会走的。
                 # 3、必须在返回传 cls
                 return super().__new__(cls)
      
           def __init__(self):
                 print("初始化音乐播放对象")
      
      player = MusicPlayer()
      print(player)
      
      对象分配空间和初始化
      上述代码中的def __new__里面如果不写 return,下面的__init__是不会走的

    四、Python 中的单例

    • 4.1、单例 —— 让 类 创建的对象,在系统中 只有 唯一的一个实例,也就是不管利用 类名()创建多少个实例对象,其内存地址都是一样的

    • 4.2、既然内存地址是一样的,那么我们就要想到 __new__方法,它是初始化内存地址的方法,我们只需要在这里进行每次返回同一个内存地址即可,具体的实现如下:

      • 定义一个 类属性
        ,初始值是 None,用于记录 单例对象的引用
      • 重写__new__ 方法
      • 如果 类属性 is None(is是用来判断内存地址是不是一样,= 是用来判断数据是不是一样),调用父类方法分配空间,并在类属性中记录结果
      • 返回 类属性 中记录的 对象引用
        单例流程
    • 4.3、单利代码示例

      class Person(object):
      
            # 定义类属性记录单例对象引用
            instance = None
      
            def __new__(cls, *args, **kwargs):
      
                  # 1. 判断类属性是否已经被赋值
                  if cls.instance is None:
                        cls.instance = super().__new__(cls)
      
                  # 2. 返回类属性的单例引用
                  return cls.instance
      
      person1 = Person()
      print(person1)
      person2 = Person()
      print(person2)
      打印结果是:
      <__main__.Person object at 0x1016c2160>
      <__main__.Person object at 0x1016c2160>
      我们可以看到上述的代码打印的 **内存地址是一样的**
      
    • 4.4、如何让 __init__代码也只初始化一次 ?我们可以模仿单利的设计模式,也定义一个 类属性 来记录是否进行过初始化,代码如下:

      class Person(object):
      
          # 定义类属性记录是否进行过初始化
          init_flag = False
          def __init__(self):
      
              # 1、判断类属性是否已经被赋值(也就是是否进行过初始化,进行过返回)
              if Person.init_flag:
                   return
              # 2、进行初始化操作
              print("进行初始化操作")
              # 3、修改init_flag的值(代表进行过初始化操作)
              Person.init_flag = True
      person1 = Person()
      person2 = Person()
      打印结果是:
      进行初始化操作
      

      通过上面可以看出来只初始化了一次

    相关文章

      网友评论

        本文标题:Python 面向对象7: 单例模式

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