zoukankan      html  css  js  c++  java
  • python设计模式之单例模式(一)

    前言

    单例模式是创建模式中比较常见和常用的模式,在程序执行的整个生命周期只存在一个实例对象。

    系列文章

    目录

    简单理解

    • 每个类创建实例化对象的时候,保证在同一个上下文环境中确保某一个类只有一个实例,减少内存的开销。

    python实现方法

    python类的实例是由__new__方法创建的,因此单例要在new方法上做文章。

    class Test(object):
    
        __instance = None
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance=object.__new__(cls) # 将实例对象用一个变量引用住,以后每次创建时直接返回该对象
            return cls.__instance
    
        def __init__(self):
            pass
    
    class Test(object):
    
        __instance = None
        __first_one = False
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance=object.__new__(cls)
            return cls.__instance
    
        def __init__(self, name):
            if not self.__first_one: # 使用一个变量的状态来记录__init__的状态,保证只初始化一次,提高运行效率
                self.__first_one = True
                self.name = name
    
    

    一般的应用场景

    • 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;比如一个对象创建时有几十上百个属性需要初始化,而初始化参数又不变的;因为object._new_(cls)方法每执行一次就会在内存中创建一个新的实例。
    class Test(object):
    
        __instance = None
        __first_one = False
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance=object.__new__(cls)
            return cls.__instance
    
        def __init__(self, name):
            if not self.__first_one: # 使用一个变量的状态来记录__init__的状态,保证只初始化一次,提高运行效率
                self.__first_one = True
                self.name1 = name
                ....
                self.name100 = "xxxx"
    
    • 工具类对象;有时为了方便管理工具函数,会让工具函数变成某个类的实例方法,但是在调用的时候要先创建一个实例,所以这个实例可以是一个单例。

    • 频繁访问数据库或文件的对象;由于涉及io操作,耗时较多,所以良好的做法是在内存中维护一个连接池,需要的时候返回一个连接对象。

    连接mysql实例

    # 以连接mysql为例
    from pymysql import *
    
    class MysqlManager(object):
        pool = [] # 设置连接池
        __instance = None
        __first_one = False
        count = 0
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
        def __init__(self, host,port,database,user,password,charset='utf8',number=5):
            if not self.__first_one:
                self.__first_one = True
                self.number = number
                self.pool = [connect(host=host, port=port, database=database,
                                    user=user, password=password, charset=charset) for i in range(number)]
    
        def __enter__(self): # 上下文管理器返回一个连接对象
            if self.count < self.number:
                con = self.pool[self.count]
                self.count += 1
                return con
            else:
                self.count = 0
                return self.pool[0]
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            pass
    
        def get_cursor(self): # 直接得到一个游标
            if self.count < self.number:
                con = self.pool[self.count]
                self.count += 1
                return con.cursor()
            else:
                self.count = 0
                return self.pool[0].cursor()
    
    
    • 多线程需要相同的创建的对象,可以使用单例共享资源优化配置。

    总结

    1. python单例模式的实现原理主要是另__new__魔法方法和__init__魔法方法每次返回的对象不变即可;

    2. 单例模式主要用在当一些场景不关心实例的属性而只关系实例的方法,即业务需要使用对象的功能,对对象本身的属性不会去改变它。

    参考

  • 相关阅读:
    软件测试笔记(二):软件测试流程
    关于Kotlin中日志的使用方法
    Github Pages+Gridea设置DisqusJS评论
    软件测试笔记(一):软件测试概论
    CVPR2021| TimeSformer-视频理解的时空注意模型
    经典论文系列 | Group Normalization & BN的缺陷
    经典论文系列 | 重新思考在ImageNet上的预训练
    CVPR2021 | 华为诺亚实验室提出Transformer in Transformer
    经典论文系列| 实例分割中的新范式-SOLO
    我们真的需要模型压缩吗
  • 原文地址:https://www.cnblogs.com/cwp-bg/p/9396813.html
Copyright © 2011-2022 走看看