首页 > 其他分享 >单例模式

单例模式

时间:2023-07-26 10:57:52浏览次数:33  
标签:__ 模式 instance 单例 new super cls

单例模式

目录

1 单例模式简介

  1. 一个类是一个类只有单个对象被创建,只能有一个实例;
  2. 自己创建这个实例;
  3. 整个系统都要使用这个实例。

1.1 为什么需要单例模式

对于有一些对象,其实例我们只需要一个,比方说:线程池、缓存(cache)、日志对象等,如果创建多个实例,就会导致许多问题产生,比如资源使用过量、程序行为不可控,或者导致不一致的结果。如:产生了很多实例,而它们做的事情只是执行发一个邮件的功能。这会特别浪费内存资源,因为频繁创建和销毁实例。

单例追求的目标:

  1. 线程安全。
  2. 懒加载:延迟加载 (懒加载)是一种将资源标识为非阻塞(非关键)资源并仅在需要时加载它们的策略。 。
  3. 调用效率高。

1.2 单例模式的基本构造

  • 私有的构造方法
  • 私有的、静态的实例化变量应用
  • 提供一个公有的、静态的获取类实例对象方法

2 代码层面理解单例模式

2.1 多例模式

  • 多例模式是一个类可以有多个对象被创建
# 多例模式
class Singleon1():
    def __init__(self, name):
        self.name = name


sin01 = Singleon1("xxx")
sin02 = Singleon1("xxx")
print(sin01)
# <__main__.Singleon1 object at 0x000001FAD4DD3DF0>
print(sin02)
# <__main__.Singleon1 object at 0x000001FAD4B62EF0>

2.2 单例模式创建

2.2.1 正常情况下的单例模式

# 单例模式
class Singleon1(object):
    instance = None  # 静态字段、类变量

    def __new__(cls, *args, **kwargs):  # cls指代当前类
        """
        创建对象
        __new__方法一定要返回一个实例对象,才会执行后面的__init__方法;
        在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。
        :param args:
        :param kwargs:
        """
        if not cls.instance:
            # cls.instance = object.__new__(cls)  # 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object
            # cls.instance = super().__new__(cls)  # super().__new__(cls) super()方法返回的即是object对象
            cls.instance = super(Singleon1, cls).__new__(cls)  # super实际传入了两个参数,第一个是本类的类型(Singleon1),第二个是类型(cls),cls即父类的类
            # cls.instance = Singleon1.__new__(cls)  # 不可调用自身的__new__方法,这样会因为执行自己的__new__()方法,造成死循环,
        return cls.instance

    def __init__(self, name):
        """
        初始化对象
        :param name:
        """
        self.name = name


sin01 = Singleon1("xxx")
sin02 = Singleon1("xxx")
print(sin01)
# <__main__.Singleon1 object at 0x000001B4524F7C40>
print(sin02)
# <__main__.Singleon1 object at 0x000001B4524F7C40>

2.2.2 threading与time下的的单例模式

  • 如果直接threading直接调用单例,产生异常。

    import threading
    import time
    
    
    # 单例模式
    class Singleon1(object):
        instance = None  # 静态字段、类变量
    
        def __new__(cls, *args, **kwargs):  # cls指代当前类
            """
            创建对象
            __new__方法一定要返回一个实例对象,才会执行后面的__init__方法;
            在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。
            :param args:
            :param kwargs:
            """
            if not cls.instance:
                time.sleep(1)
                # cls.instance = object.__new__(cls)  # 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object
                # cls.instance = super().__new__(cls)  # super().__new__(cls) super()方法返回的即是object对象
                cls.instance = super(Singleon1, cls).__new__(cls)  # super实际传入了两个参数,第一个是本类的类型(Singleon1),第二个是类型(cls),cls即父类的类
                # cls.instance = Singleon1.__new__(cls)  # 不可调用自身的__new__方法,这样会因为执行自己的__new__()方法,造成死循环,
            return cls.instance
    
        def __init__(self, name):
            """
            初始化对象
            :param name:
            """
            self.name = name
    
    
    def func():
        obj = Singleon1("xxx")
        print(obj)
    
    for i in range(10):
        task = threading.Thread(target=func)
        task.start()
    
    # <__main__.Singleon1 object at 0x0000017B7E5A2170>
    # <__main__.Singleon1 object at 0x0000017B7E7A3460>
    # <__main__.Singleon1 object at 0x0000017B7E5A2170>
    # <__main__.Singleon1 object at 0x0000017B7E7A3B20>
    # <__main__.Singleon1 object at 0x0000017B7E7A3EE0>
    # <__main__.Singleon1 object at 0x0000017B7E5A2170>
    # <__main__.Singleon1 object at 0x0000017B7E7A3B20>
    # <__main__.Singleon1 object at 0x0000017B7E7E9B40>
    # <__main__.Singleon1 object at 0x0000017B7E5A2170>
    # <__main__.Singleon1 object at 0x0000017B7E7A3460>
    
  • 需要对使用单例模式的类进行加锁

    import threading
    import time
    
    
    # 单例模式
    class Singleon1(object):
        instance = None  # 静态字段、类变量
        rlock = threading.RLock()
    
        def __new__(cls, *args, **kwargs):  # cls指代当前类
            """
            创建对象
            __new__方法一定要返回一个实例对象,才会执行后面的__init__方法;
            在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。
            :param args:
            :param kwargs:
            """
            if cls.instance:
                return cls.instance
            with cls.rlock:
                if not cls.instance:
                    time.sleep(1)
                    cls.instance = object.__new__(cls)  # 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object
                    # cls.instance = super().__new__(cls)  # super().__new__(cls) super()方法返回的即是object对象
                    # cls.instance = super(Singleon1, cls).__new__(cls)  # super实际传入了两个参数,第一个是本类的类型(Singleon1),第二个是类型(cls),cls即父类的类
                    # cls.instance = Singleon1.__new__(cls)  # 不可调用自身的__new__方法,这样会因为执行自己的__new__()方法,造成死循环,
                return cls.instance
    
    
        def __init__(self, name):
            """
            初始化对象
            :param name:
            """
            self.name = name
    
    
    def func():
        obj = Singleon1("xxx")
        print(obj)
    
    for i in range(10):
        task = threading.Thread(target=func)
        task.start()
    
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    # <__main__.Singleon1 object at 0x0000024392DA2170>
    
  • 或使用模块引用方式

    Singleon2_test.py
    # 单例模式
    class Singleon2(object):
        pass
    
    
    obj = Singleon2()
    
    
    
    test.py
    from Singleon2_test import obj
    
    if __name__ == '__main__':
        print(obj)
        print(obj)
        print(obj)
        print(obj)
    # <Singleon2_test.Singleon2 object at 0x000002C645007C40>
    # <Singleon2_test.Singleon2 object at 0x000002C645007C40>
    # <Singleon2_test.Singleon2 object at 0x000002C645007C40>
    # <Singleon2_test.Singleon2 object at 0x000002C645007C40>
    

标签:__,模式,instance,单例,new,super,cls
From: https://www.cnblogs.com/f-carey/p/17581833.html

相关文章

  • C++ 单例模式三种写法
    #include<iostream>#include"Apple.h"#include"Singleton.h"#include"ActivityManager.h"#include"ResourceManager.h"usingnamespaceMySpace;intmain(){Apple::abc=10;//参考:https://blog.csdn.n......
  • 设计模式(1)-单例模式
    单例模式饿汉式懒汉式懒汉双加锁静态内部类C#特有写法破坏单例定义:有且仅有一个实例,节省资源。构造函数私有化静态只读私有字段静态公开的获取私有字段的方法饿汉式publicclassHungryMan{//构造函数私有化privateHungryMan(){}//静态只读私有字段......
  • python单例类
    Python单例类的实现方法概述在Python中,单例模式是一种常见的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。在某些情况下,需要确保一个类的对象在整个程序中只被创建一次,以避免资源的浪费。本文将介绍如何在Python中实现单例类,并提供一个详细的步骤,以便新手开发者能够......
  • 23种设计模式介绍
    面向对象23种设计模式设计模式的分类按意图分类接口型模式职责型模式构造型模式操作型模式扩展型模式意图模式接口型模式适配器模式、外观模式、合成模式、桥接模式职责型模式代理模式,享元模式、单例模式、观察者模式、调停者模式、职责链模式构造型模......
  • 利用策略模式结合Springboot框架
    利用策略模式解决多条件问题问题重现这是公司代码里面的一个接口,我需要根据type的不同,去决定要不要存储里面的对象。ini复制代码@Transactional(rollbackFor=Exception.class)@OverridepublicbooleansaveDimensionsByQuestionBankId(List<MbDimensionsDto>dimensio......
  • 设计模式-职责链模式在Java中使用示例-采购审批系统
    场景采购单分级审批采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批5万元以下(不包括5万元)的采购单,副董事长可以审批5万元至10万元(不包括10万元)的采购单,董事长可以审批10万元至50万元(不包括50万元)的采购单,50万元及以上的采购单就需要开董事会......
  • .NET(C#) 设计模式
    .NET(C#)设计模式简介设计模式(Designpattern)是代码设计经验的总结。设计模式主要分三个类型:创建型、结构型和行为型。创建型是对象实例化的模式,创建型模式用于解耦对象的实例化过程,主要用于创建对象。结构型是把类或对象结合在一起形成一个更大的结构,主要用于优化不同类、对......
  • 设计模式—享元模式
    享元模式享元模式(FlyweightPattern)是池技术的重要实现方式,其定义如下:Usesharingtosupportlargenumbersoffine-grainedobjectsefficiently.(使用共享对象可有效地支持大量的细粒度的对象。)优点与缺点享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降......
  • 设计模式—组合模式
    组合模式目录组合模式优点缺点使用场景注意事项例子组合模式(CompositePattern)也叫合成模式,有时又叫做部分-整体模式(Part-Whole),主要是用来描述部分与整体的关系。将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。优点......
  • 设计模式—状态模式
    状态模式目录状态模式优点缺点适用场景注意事项通用类图例子状态模式与策略模式的差异当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样。优点结构清......