python中的单例模式介绍和使用

一、什么是单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
单例设计模式:
**目的:**让类创建的对象,在系统只执行唯一实例,即每一次执行类名.()返回的对象,内存地址是相同的,可以通过id(实例对象)来查看实例对象对应的内存空间地址。
应用场景: 音乐播放器、回收站对象、打印机对象…

二、通过装饰器实现单例模式

面试真题:

  • 装饰器介绍
    在原函数不改变的基础上增加额外功能

  • 通过装饰器实现单例模式,只要任意一个类使用该装饰器装饰,
    那么就会变成一个单例模式的类。

1.用函数方法实现:

def single(cls):
    cls.instance = None

    def wrapper(*args, **kwargs):
        # 判断类是否有instance属性
        if not cls.instance:
            # 通过类创建对象,并保存为instance属性
            cls.instance = cls(*args, **kwargs)
        # 返回对象
        return cls.instance

    return wrapper
@single  # A = single(A)
class A:
    pass
a1 = A()
a2 = A()
print(a1, a2)

运行结果:

<__main__.A object at 0x000001F125DE2D60> <__main__.A object at 0x000001F125DE2D60>

2.通过类来实现:

class single1:
    def __init__(self, cls):
        self.cls = cls
        self.cls.instance = None

    def __call__(self, *args, **kwargs):
        if not self.cls.instance:
            self.cls.instance = self.cls(*args, **kwargs)
        return self.cls.instance
@single1  
class B:
    pass
b1 = B()
b2 = B()
print(b1, b2) 

运行结果:

<__main__.A object at 0x0000017C66BD05B0> <__main__.A object at 0x0000017C66BD05B0>

三、基于基于__new__方法实现
__new__方法:

  1. 使用类名()创建对象时,python的解释器首先会调用__new__方法为对象分配空间,然后在执行__init__初始话实例对象。

  2. object提供的__new__静态方法,主要有2个作用:
    1.在内存中为对象分配空间
    2.返回对象的引用

  3. object提供的__new__静态方法,主要有2个作用:
    注意点:
    1.重写__new__方法一定要return super().new(cls), 否则python解释器得不到分配空间引用,就不会调用对象的初始化
    2.__new__是一个静态方法,在调用时需要主动传递cls函数。

代码实现:


#super():如果多继承情况下会出现一个子类继承多个父类,每个父类都要单独被调用,会特别麻烦,在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照MRO(Method Resolution Order):方法解析顺序 进行的。
class A(object):
	__instance = None
	def __new__(cls, *args, **kwargs):
		if cls.__instance is None:
			cls.__instance = super().__new__(cls)
			return cls.__instance
		else:
			return cls.__instance


a1 = A()
a2 = A()
print("a1的id为:", id(a1))
print("a2的id为:", id(a2))
print(a1)
print(a2)

运行结果:

a1的id: 2552498755664
a2的id: 2552498755664
<__main__.A object at 0x000002524CC81850>
<__main__.A object at 0x000002524CC81850>

解析如下:

  • 目的:
    让类创建的对象,在系统中只有唯一的一个实例

  • 流程:
    1.定义一个类属性,初始值是None, 用于记录单例对象的引用。
    2.重写__new__方法
    3.如果类属性is None,调用父类方法分配空间,并在类属性中记录结果
    返回类属性中记录的对象引用。

猜你喜欢

转载自blog.csdn.net/weixin_49319422/article/details/125426266