zoukankan      html  css  js  c++  java
  • 单例设计模式

    目标:

    1. 单例设计模式
    2. __new__方法
    3. Python中的单例

    1.单例设计模式

    • 设计模式:
      • 设计模式前人工作的总结和提炼,通常,被人们广泛流传的设计模式,都是针对 某一特定问题 的成熟的解决方案
      • 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
    • 单例设计模式
      • 目的——让 创建的对象,在系统中只有 唯一的一个实例
      • 每一次执行 类名() 返回的对象,内存地址是相同的
    • 单例设计模式的应用场景
      • 音乐播放 对象
      • 回收站 对象
      • 打印机 对象
      • ········

    2.__new__方法

    • 使用 类名() 创建对象时,Python解释器会先调用__new__方法为对象分配空间,再调用__init__()方法初始化对象
    • __new__是由object基类提供的内置的静态方法,主要作用有两个
      1. 在内存中为对象分配空间
      2. 返回对象的引用
    • Python解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法
    •  1 class MusicPlayer(object):
       2     def __new__(cls, *args, **kwargs):
       3         print("创建对象,分配空间")
       4 
       5     def __init__(self):
       6         print("初始化对象")
       7 
       8 player = MusicPlayer()
       9 print(player)
      10 '''
      11 运行结果:
      12 创建对象,分配空间  :可以看出在实例化对象时,先调用了new方法为对象开辟空间
      13 None    :因为重写了new方法,而new方法需要将对象的地址传递给init,
      14           重写时并没有做,所以没有进行初始化
      15 '''
      View Code
    • 重写__new__方法的代码非常的固定
      1. 一定要  return super().__new__(cls)
      2. 否则Python解释器得不到分配了空间的引用,就不会调用对象的初始化方法
      3. 注意:__new__是一个静态方法,在调用时需要主动传递cls参数
      • class MusicPlayer(object):
            def __new__(cls, *args, **kwargs):
                #创建对象时,new方法会自动被调用
                print("创建对象,分配空间")
                #为对象分配空间
                instance = super().__new__(cls)
                #返回对象的引用
                return instance
            def __init__(self):
                print("初始化对象")
        
        player = MusicPlayer()
        print(player)
        '''
        运行结果:
        创建对象,分配空间
        初始化对象
        <__main__.MusicPlayer object at 0x000001DC63B9FF10>
        '''
      • 单例——让类创建的对象,在系统中只有唯一的一个实例
        1. 定义一个 类属性,初始值是None,用于记录单例对象的引用
        2. 重写new方法
        3. 如果类属性 is None,调用父类方法分配空间,并在类属性中记录结果
        4. 返回类属性中记录的对象引用
      •  1 #单例设计模式
         2 class MusicPlayer(object):
         3     instance = None     #记录对象的地址
         4     def __new__(cls, *args, **kwargs):
         5         #判断对象是否为空,如果为空,就为其分配地址
         6         if cls.instance is None:
         7             #为对象分配空间
         8             cls.instance = super().__new__(cls)
         9             #返回对象的引用
        10             return cls.instance
        11         #如果部位空,就返回第一个对象的地址
        12         else:
        13             return cls.instance
        14     def __init__(self):
        15         pass
        16 
        17 player_1 = MusicPlayer()    #<__main__.MusicPlayer object at 0x00000282C8B7FDF0>
        18 print(player_1)
        19 
        20 player_2 = MusicPlayer()    #<__main__.MusicPlayer object at 0x00000282C8B7FDF0>
        21 print(player_2)
        单例设计模式案例
    • 只执行一次初始化动作
      • 需求:让初始化动作只被执行一次
      • 解决办法
        1. 定义一个类属性init_flag标记是否 执行过初始化动作,初始值为False
        2. 在 __init__ 方法中,判断init_flag,如果为False就执行初始化动作
        3. 然后将init_flag设置为True
        4. 这样,再次调用__init__方法时,初始化动作就不会被执行了
      •  1 #初始化动作只执行一次
         2 class MusicPlayer(object):
         3     instance = None     #记录对象的地址
         4     init_flag = False   #标记是否执行过初始化动作
         5     def __new__(cls, *args, **kwargs):
         6         #判断对象是否为空,如果为空,就为其分配地址
         7         if cls.instance is None:
         8             #为对象分配空间
         9             cls.instance = super().__new__(cls)
        10             #返回对象的引用
        11             return cls.instance
        12         #如果部位空,就返回第一个对象的地址
        13         else:
        14             return cls.instance
        15     def __init__(self):
        16         #判断初始化动作是否执行过
        17         if MusicPlayer.init_flag:
        18             return
        19         #如果没有执行过,那么执行初始化动作
        20         print("初始化播放器")
        21         #修改类属性(init_flag)的标记
        22         MusicPlayer.init_flag = True
        23 
        24 player_1 = MusicPlayer()    #<__main__.MusicPlayer object at 0x00000282C8B7FDF0>
        25 print(player_1)
        26 player_2 = MusicPlayer()    #<__main__.MusicPlayer object at 0x00000282C8B7FDF0>
        27 print(player_2)
        28 player_3 = MusicPlayer()    #<__main__.MusicPlayer object at 0x00000282C8B7FDF0>
        29 print(player_3)
        30 '''
        31 运行结果:
        32 初始化播放器
        33 <__main__.MusicPlayer object at 0x0000029ECB252F10>
        34 <__main__.MusicPlayer object at 0x0000029ECB252F10>
        35 <__main__.MusicPlayer object at 0x0000029ECB252F10>
        36 '''
        只执行一次初始化动作

     

  • 相关阅读:
    Java对MongoDB的CRUD
    MongoDB数据库基本用法
    MySQL order by 排序结果不正确
    Linux shell 脚本 eq,ne,le,ge,lt,gt意义
    Linux shell 命令运行符 &,;,&& 区别
    Linux netstat 命令详解
    Linux ss 命令详解
    Linux sort 命令详解
    Linux sed 命令详解
    Linux xargs 命令详解
  • 原文地址:https://www.cnblogs.com/fjfsu/p/15458718.html
Copyright © 2011-2022 走看看