• Python中的单例类


    目录

    一、单例模式的概述

    二、单例模式的优缺点

    三、在Python中,单例模式有以下几种实现方式

    1.通过魔法方法__new__实现

    2.通过模块的导入

    3.通过装饰器实现

    4.通过使用类实现


    一、单例模式的概述

            单例模式是一种常用的软件设计模式。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

    注意:

    • 1、单例类只能有一个实例。
    • 2、单例类必须自己创建自己的唯一实例。
    • 3、单例类必须给所有其他对象提供这一实例。

    从具体实现角度来说,就是以下三点:

    • 1.单例模式的类只提供私有的构造函数,
    • 2.类定义中含有一个该类的静态私有对象,
    • 3.该类提供了一个静态的共有函数用于创建或获取它本身的静态私有对象。

    二、单例模式的优缺点

    优点:

            (1) 由于单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建销毁时,而且创建或销毁时性能又无法优化,单例模式就非常明显了

            (2) 由于单例模式只生成一个实例,所以,减少系统的性能开销,当一个对象产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

            (3) 单例模式可以避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作

    缺点:

            (1) 单例模式没有抽象层,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。

            (2) 单例类的职责过重,在一定程度上违背了“单一职责原则”。

            (3) 滥用单例将带来一些负面问题,如:为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;

    三、在Python中,单例模式有以下几种实现方式

    1.通过魔法方法__new__实现

    1. class Demo1(object):
    2. def __new__(cls, *args, **kwargs):
    3. # 判断单例是否存在:_instance属性中存储的就是单例
    4. if not hasattr(cls,'_instance'):
    5. # 如果单例不存在,初始化单例
    6. cls._instance= super(类名,cls).__new__(cls,*args,**kwargs)
    7. # 返回单例
    8. return cls._instance
    '
    运行

    2.通过模块的导入

    1. # cls_singleton.py
    2. class Foo(object):
    3. pass
    4. instance = Foo()
    5. # test.py
    6. import cls_singleton
    7. obj1 = cls_singleton.instance
    8. obj2 = cls_singleton.instance
    9. # 原理:模块第二次导入从内存找的机制

    3.通过装饰器实现

    1. def singleton(cls):
    2. # 创建一个字典用来保存类的实例对象
    3. _instance = {}
    4. def _singleton(*args, **kwargs):
    5. # 先判断这个类有没有对象
    6. if cls not in _instance:
    7. _instance[cls] = cls(*args, **kwargs) # 创建一个对象,并保存到字典当中
    8. # 将实例对象返回
    9. return _instance[cls]
    10. return _singleton
    11. @singleton
    12. class Demo3(object):
    13. a = 1
    14. def __init__(self, x=0):
    15. self.x = x
    16. a1 = Demo3(1)
    17. a2 = Demo3(2)
    18. print(id(a1))
    19. print(id(a2))
    '
    运行

    4.通过使用类实现

    1. class Demo4(object):
    2. # 静态变量
    3. _instance = None
    4. _flag = False
    5. def __new__(cls, *args, **kwargs):
    6. if cls._instance is None:
    7. cls._instance = super().__new__(cls)
    8. return cls._instance
    9. def __init__(self):
    10. if not Demo3._flag:
    11. Demo4._flag = True
    '
    运行

  • 相关阅读:
    物联网浏览器(IoTBrowser)-整合机器学习yolo框架实现车牌识别
    ​LeetCode解法汇总307. 区域和检索 - 数组可修改
    React +AntD + From组件重复提交数据(已解决)
    Linux--信号携带消息
    springboot实现国际化
    NodeJs实战-待办列表(2)-待办列表增删
    docsify搭建个人博客——简单公共知识库
    elementUi里的时间选择器显示默认时间为0点并将标准格式转换为xxxx年xx月xx日 xx时xx分xx秒
    【MindSpore易点通】调优精度之低阶API使用动态LossScale
    使用 Spring Data MongoDB 连接到多个数据库
  • 原文地址:https://blog.csdn.net/m0_61491995/article/details/126948021