python如何实现单例模式?(面试重点,必会!!!)

什么是单例模式(Singleton)?

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。

如何实现单例的方式?(四种方法)

  • 全局变量:不直接调用 Config() ,而使用同一个全局变量
  • 重写 __new__ 方法:重写 __new__ 来保证每次调用 Config() 都会返回同一个对象,__new__为对象分配空间,返回对象的引用
  • 使用metaclass:metaclass重写__call__ 方法来保证每次调用 Config() 都会返回同一个对象
  • 使用装饰器:使用装饰器来保证每次调用 Config() 都会返回同一个对象

原理:在真正调用 Config() 之前进行一些拦截操作,来保证返回的对象都是同一个:

1. 全局变量
# config.py
from dataclasses import dataclass

@dataclass
class Config:
    SQLALCHEMY_DB_URI = SQLALCHEMY_DB_URI
config = Config(SQLALCHEMY_DB_URI  = "mysql://"``)

通过使用全局变量,我们在所有需要引用配置的地方,都使用 from config import config 来导入,这样就达到了全局唯一的目的。

2. 重写new方法
class Singleton(object):
    _instance = None   # _instance 作为类属性,保证了所有对象的实例都是同一个

    def __new__(cls, *args, **kwargs):  
        if cls._instance is None:
            cls._instance = super().__new__(cls)  # 为对象分配空间
        return cls._instance   # 返回对象的引用

a = Singleton()    # 创建对象时,new方法会被自动调用
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x0000023A88E0F2B0>
		<__main__.Singleton object at 0x0000023A88E0F2B0>

每次实例化一个对象时,都会先调用 __new__() 创建一个对象,再调用 __init__() 函数初始化数据。因而,在 new 函数中判断 Singleton类 是否已经实例化过,如果不是,调用父类的 new 函数创建实例;否则返回之前创建的实例。

3. 使用metaclass元类
class SigletonMetaClass(type):
    _instance = None

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

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

class Singleton(metaclass=SigletonMetaClass):
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls)
    
a = Singleton()
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x000001A11E4AC908>
		<__main__.Singleton object at 0x000001A11E4AC908>

因此,用元类实现单例时仍需按照三步骤:1. 拦截 2. 判断是否已经创建过对象 3. 返回对象。与上个方法相比,区别在于拦截的地点不同。

4. 装饰器
4.1 函数装饰器
def SingletonDecorator(cls):
    _instance = None

    def get_instance(*args, **kwargs):
        nonlocal _instance
        if _instance is None:
            _instance = cls(*args, **kwargs)
        return _instance
    return get_instance

@SingletonDecorator
class Singleton(object):
    pass

a = Singleton()
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x0000022194E6C438>
		<__main__.Singleton object at 0x0000022194E6C438>
4.2 类装饰器
class SingletonDecorator(object):
    _instance = None

    def __init__(self, cls):
        self._cls = cls

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

@SingletonDecorator
class Singleton(object):
    pass

a = Singleton()
b = Singleton()
print(a)
print(b)
执行结果:<__main__.Singleton object at 0x0000028F42CFC8D0>
		<__main__.Singleton object at 0x0000028F42CFC8D0>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值