3分钟学会设计模式 -- 单例模式

2644 篇文章 26 订阅
2474 篇文章 14 订阅

►单例模式

图片

►使用场景

在编写软件时,对于某些类来说,只有一个实例很重要。例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统中可以多次查询数据库,但是只需要一个连接,而不是每次查询都重新创建一个连接,因为重复创建数据库连接会浪费内存资源。因此这种情况下确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

如何保证一个类只有一个实例并方便访问呢?定义一个全局变量可以确保对象随时可以访问,但不能防止实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的使用场景。

►python实现

python中实现单例模式的方法很多,常用方法如下:

重写__new__

类实例化时是调用__new__方法创建对象的,所以只要控制__new__方法创建对象是只生成一个实例即可。

class DB:
    instance = None


    def __new__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super().__new__(cls, *args, **kwargs)
        return cls.instance
db1 = DB()
db2 = DB()
print(db1)
print(db2)

运行代码结果如下:

<__main__.DB object at 0x000001BD06E55F70>
<__main__.DB object at 0x000001BD06E55F70>

►装饰器

将类的唯一实例保存在类属性上,然后通过类装饰器,在实例化时检查这个属性来控制只生成一个实例。

def single_obj(cls):
    def wrapper(*args, **kwargs):
        if cls.instance is None:
            cls.instance = cls(*args, **kwargs)
        return cls.instance
    return wrapper

@single_obj
class DB:
    instance = None

db1 = DB()
db2 = DB()
print(db1)
print(db2)

运行代码结果如下:

<__main__.DB object at 0x000001E485395970>
<__main__.DB object at 0x000001E485395970>

►元类

python中元类是用于创建类对象的类,类对象创建实例对象时一定会调用__call__方法,因此重写元类的__call__方法,保证在调用__call__时只创建一个实例即可。

class SingleObj(type):
    def __call__(cls, *args, **kwargs):
        if getattr(cls, 'instance', None) is None:
            cls.instance = super().__call__(*args, **kwargs)
        return cls.instance

class DB(metaclass=SingleObj):
    pass

db1 = DB()
db2 = DB()

print(db1)
print(db2)

代码运行结果如下:

<__main__.DB object at 0x00000252D5AE4F70>
<__main__.DB object at 0x00000252D5AE4F70>

在这里还是要推荐下我自己建的软件测试学习Q群:746506216,群里都是学测试的,如果你想学或者正在学习测试,欢迎你加入,大家都是测试党,不定期分享干货(只有软件测试相关的),包括我自己整理的一份2022最新的Python自动化测试进阶资料和零基础教学,欢迎进阶中和对测试感兴趣的小伙伴加入!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值