• Python实现单例模式


    Python实现单例模式

    单例模式

    介绍
    意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
    主要解决:一个全局使用的类频繁地创建与销毁。
    何时使用:当您想控制实例数目,节省系统资源的时候。
    如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
    关键代码:构造函数是私有的。
    应用实例:
    1、一个班级只有一个班主任。
    2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
    3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
    优点:
    1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
    2、避免对资源的多重占用(比如写文件操作)。
    缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
    使用场景:
    1、要求生产唯一序列号。
    2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
    3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
    

      

    第一种方法

     1 class User(object):
     2     #定义类属性
     3     __instance=None
     4     #初始化方法
     5     def __init__(self,name):
     6         self.name=name
     7 
     8     @classmethod
     9     #定义类方法
    10     def get_instance(cls,name):
    11         #如果__instance为空,则执行
    12         if not cls.__instance:
    13             #实例化对象,并赋值给__instance属性
    14             cls.__instance=User(name)
    15         return cls.__instance
    16 u1 =User.get_instance("lili")
    17 u2 = User.get_instance("lisi")
    18 print(u1==u2)
    19 print(id(u1))
    20 print(id(u2))
    运行结果:
    True 41816192 41816192

      

    代码分析

    # 要实现不管实例化多少次,拿到的都是同一个对象
    # 这里我们通过调用类的静态方法来实例化类(@classmethod)
    # 第一次实例化对象的时候,类属性为空,则会初始化对象,并返回对象
    # 第二次时,类属性已不为空,则不会实例化对象,直接返回第一次生成的对象
    关键点:通过类静态方法实例化对象
         __instance类属性的作用

    补充classmethod

    classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。
    View Code

    这里name是否相同?

    # 我们是使用通过调用类的静态方法来实例化对象的,所以这里不会直接执行__init__方法,是在静态方法里间实例化时执行了__init__方法,并且只会执行一次。
    # 这里每次实例化一次对象,拿到的对象是同一个对象,name也相同。

     

    有一个问题?我们知道有两种方法初始化对象,如果我们使用User("lili")来实例化对象会怎样?

    # 第一种:u1=User("lili")  #通过 __init__实例化对象
    # 第二种:u1=get_instance("lili")  #通过类的静态方法间接实例化对象
    

      

    class User(object):
        #定义类属性
        __instance=None
        #初始化方法
        def __init__(self,name):
            self.name=name
    
        @classmethod
        #定义类方法
        def get_instance(cls,name):
            #如果__instance为空,则执行
            if not cls.__instance:
                #实例化对象,并赋值给__instance属性
                cls.__instance=User(name)
            return cls.__instance
    u1 =User("lili")
    u2 = User("lisi")
    print(u1==u2)
    print(id(u1))
    print(id(u2))
    代码
    False
    36376704
    36376760
    

      

    第二种方法

     1 class User(object):
     2     #定义类属性
     3     __instance=None
     4     #初始化方法
     5     def __init__(self,name):
     6         self.name=name
     7     def __new__(cls,name):
     8         #保证object.__new__(cls)方法只会调用第一次
     9         if not cls.__instance:
    10             #object.__new__(cls)创建对象
    11             cls.__instance=object.__new__(cls)
    12         return cls.__instance
    13 u1 = User("lili")
    14 u2 = User("lisi")
    15 print(u1==u2)
    16 print(id(u1))
    17 print(id(u2))
    运行结果:
    True 42106384 42106384

      

    代码分析

    #当代码执行u1 = User("lili")
    # 会运行到__new__方法,此时类属性__instance为空,则会创建对象,把对象赋值给__instance,并返回对象
    # 现在代码还没有运行完,会继续执行__init__方法,会将"lili"赋值给name,现在name="lili"
    # 执行u1 = User("lili"),类属性不为空,不会创建对象,直接返回第一次创建的对象
    #此时是最重要的,def __init__(self,name)中self为第一次的对象,而传进来的name为第二次的name,就会将"lisi"赋值给name,现在name="lisi"
    # 但是对象永远都是那个对象,name却不是那个name了。
    #所以这里每次实例化一次对象,虽然对象还是那个对象,但是name会不一样。

      

  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/-wenli/p/10433503.html
Copyright © 2020-2023  润新知