• Python 单例设计模式


    设计模式

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

    单例设计模式

    • 目的 -- 让类创建对象,在系统中只有唯一的一个实例
    • 每一次执行 类名() 返回的对象,内存地址是相同的


    单例设计模式应用场景
    音乐播放器 对象
    打印机 对象
    ......

    __new__ 方法

    • 使用 类名() 创建对象时,Python 的解释器首先会调用 __new__ 方法为对象分配空间
    • __new__ 是一个由 object 基类提供的 内置的静态方法,主要作用有两个:
    1. 在内存中为对象分配空间
    2. 返回对象引用

      

    Python 解释器获得对象引用后,将引用的第一个参数,传递给 __new__ 方法

    重写 __new__ 方法的代码非常固定!

      1.  重写 __new__ 方法一点要 return super().__new__(cls)
      2.  否则 Python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
      3.  注意:__new__ 是一个静态方法,在调用是需要主动传递 cls 参数
    class MusicPlayer(object):
        def __new__(cls,*args,**kwargs):
            #1、创建对象时,new方法会被自动调用
            print("创建对象,分配空间...")
    
            #2、为对象分配空间
            instance = super().__new__(cls)
            
            #3、返回对象的引用
            return instance
    
        def __init__(self):
            print("播放器初始化...")
    
    #创建对象
    player = MusicPlayer()
    print(player)

    运行结果为:

    创建对象,分配空间...
    播放器初始化...
    <__main__.MusicPlayer object at 0x0000000002F64F28>

    单例创建流程

    1. 定义一个类属性,初始值是None,用于记录单例对象的应用
    2. 重写 __new__ 方法
    3. 如果类属性 is None ,调用父类方法分配空间,并在类属性中记录结果
    4. 返回类属性中记录的对象引用
    class MusicPlayer(object):
        #记录第一个被创建对象的引用
        instance = None
        
        def __new__(cls,*args,**kwargs):
            #1、判断类属性是否是空对象
            if cls.instance is None:
                #2、调用父类方法,为第一个对象分配空间
                cls.instance = super().__new__(cls)
            
            #3、返回类属性保存的对象引用
            return cls.instance
    
    
    #创建多个对象
    player1 = MusicPlayer()
    print(player1)
    
    player2 = MusicPlayer()
    print(player2)

    结果为:

    <__main__.MusicPlayer object at 0x0000000002FF5BA8>
    <__main__.MusicPlayer object at 0x0000000002FF5BA8>

    只执行一次初始化动作

    每次调用 类名() 创建对象时,Python解释器会自动调用两个方法:

    1. __new__ 分配空间
    2. __init__ 对象初始化

    解决办法:

    1. 定义一个类属性 init_flag 标记是否执行过初始化动作,初始值为 False
    2. 在 __init__ 方法中,判断 init_flag,如果为 False 就执行初始化动作
    3. 然后将 init_flag 设置为 True
    4. 这样,再次调用 __init__ 方法世,初始化动作就不会再执行了
    class MusicPlayer(object):
        #记录第一个被创建对象的引用
        instance = None
    
        #记录是否执行过初始化动作
        init_flag = False
        
        def __new__(cls,*args,**kwargs):
            #1、判断类属性是否是空对象
            if cls.instance is None:
                #2、调用父类方法,为第一个对象分配空间
                cls.instance = super().__new__(cls)
            
            #3、返回类属性保存的对象引用
            return cls.instance
    
        def __init__(self):
            #1、判断是否执行过初始化动作
            if MusicPlayer.init_flag:
                return
            
            #2、如果没有执行过,在执行初始化动作
            print("初始化播放器...")
                
            #3、修改类属性的标记
            MusicPlayer.init_flag = True
            
    
    #创建多个对象
    player1 = MusicPlayer()
    print(player1)
    
    player2 = MusicPlayer()
    print(player2)

    结果为:

    初始化播放器...
    <__main__.MusicPlayer object at 0x0000000003009B70>
    <__main__.MusicPlayer object at 0x0000000003009B70>

    原贴:https://www.cnblogs.com/diyi/p/9390000.html

  • 相关阅读:
    IntelliJ IDEA 14.03 java 中文文本处理中的编码格式设置
    应聘感悟
    STL string分析
    CUDA SDK VolumeRender 分析 (1)
    BSP
    CUDA SDK VolumeRender 分析 (3)
    CUDA SDK VolumeRender 分析 (2)
    Windows软件发布时遇到的一些问题
    Ten Commandments of Egoless Programming (转载)
    复习下光照知识
  • 原文地址:https://www.cnblogs.com/mswei/p/9393957.html
Copyright © 2020-2023  润新知