【设计模式】单例模式

这篇博客详细介绍了Python中实现单例模式的四种方式:类重写__new__方法、装饰器、元类以及加锁优化。单例模式主要用于确保某个类只有一个实例,常用于配置、日志和连接池等场景,以避免资源浪费并保证多线程环境下的数据安全。文章通过示例代码展示了每种实现方法,并讨论了在多线程环境下的安全性问题。
摘要由CSDN通过智能技术生成
1.说明

单例即只有一个实例,比如说配置、日志、连接池等,可以避免多个实例带来的多余的资源开销,并且在多线程环境下保证数据安全

2.类重写__new__
class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super().__new__(cls, *args, **args)
        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(id(s1), id(s2), s1 is s2)
3.装饰器

我们可以使用functools里的wraps装饰一下,它能保留原有函数的名称和函数属性

from functools import wraps

def singleton(cls):
    instance = dict()

    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]
    return wrapper

@singleton
class Person:
    pass

s1 = Person()
s2 = Person()
print(id(s1), id(s2), s1 is s2)

4.元类

type创建类时自动调用__init__(),类在创建对象时会自动调用__call__()

class SingletonMeta(type):
    def __init__(cls, *args, **kwargs):
        cls._instance = None
        super().__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance

class Person(metaclass=SingletonMeta):
    pass

s1 = Person()
s2 = Person()
print(id(s1), id(s2), s1 is s2)
5.加锁优化

如果不加锁,在多线程情况下可能会同时实例化对象

from threading import RLock

class Singleton:
    _instance = None
    _lock = RLock()

    def __new__(cls, *args, **kwargs):
        if cls._instance:
            return cls._instance
        with cls._lock:
            if not cls._instance:
                super().__new__(cls, *args, **kwargs)
            return cls._instance

s1 = Singleton()
s2 = Singleton()
print(id(s1), id(s2), s1 is s2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰冷的希望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值