单例模式

发布时间 2024-01-09 19:17:33作者: -半城烟雨

单例模式

【一】什么是设计模式

  • 解决问题的模板,大牛们会遇到各种各样的问题,长久一来就形成了一套相对规范的解决办法

【二】使用模式的好处

  • 设计模式可以帮助开发人员编写高质量、可重用和易于维护的代码
  • 通过使用设计模式,开发人员可以避免重复劳动,并确保他们的代码遵循最佳实践和行业标准

【三】设计模式的组成部分

【1】问题:有了问题才需要想解决办法

【2】解决方按:对上述问题拟定方案解决

【3】关键角色:到底应该用在哪里?谁来用我?

【四】常见的设计模式

  • 常见的设计模式有单例模式、工厂模式、观察者模式、适配器模式、策略模式、装饰器模式、代理模式等。

【五】什么是单例模式

  • 单例设计模式(Singleton Design Pattern): 一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
  • 当一个类的功能比较单一,只需要一个实例对象就可以完成需求时,就可以使用单例模式来节省内存资源。
class MyMeta(type):
    def __init__(cls, what, bases, dict):
        print(f'这是 __init__ {cls}')
        cls.instance = None
        super().__init__(what, bases, dict)

    def __new__(cls, *args, **kwargs):
        obj = super().__new__(cls, *args, **kwargs)
        print(f'这是 __new__ {obj}')
        return obj

    def __call__(self, *args, **kwargs):
        # print(f'这是 __call__ {self}')
        obj = super().__call__(*args, **kwargs)
        # if hasattr(self, 'instance'):
        #     return getattr(self, 'instance')
        if self.instance:
            return self.instance
        self.instance = obj
        print(self.instance)
        return obj
# 元类是控制类的产生的
# 元类里面的所有 self 如果不是你想产生的这个类

class School(metaclass=MyMeta):
    ...

# 控制对象的产生,我们要重写 元类中 的 __call__
s = School()
s1 = School()
print(id(s))
print(id(s1))
  1. __init__方法:在类被创建时调用。这个方法用于初始化类的属性和状态。在这里,我们设置了一个名为instance的属性,用于保存类的唯一实例。
  2. __new__方法:在类被创建时调用。这个方法用于创建类的实例。在这里,我们调用了父元类的__new__方法来创建实例对象,并返回这个实例。
  3. __call__方法:在类的实例被调用时调用。这个方法提供了类似函数调用的方式来创建对象。在这里,我们通过判断self.instance是否存在来决定是否返回已有的实例。如果已有实例存在,则直接返回该实例;如果不存在,则创建一个新的实例,并将其保存到self.instance中。

整体来说,这个元类实现了单例模式的逻辑。通过使用这个元类创建的类MyClass,无论在何处创建实例,都会得到同一个对象。这样可以确保全局只有一个实例存在,并避免了资源浪费和状态不一致的问题。

【六】单例模式补充

# 定义元类
class MyMeta(type):
    # 定义一个类属性
    instance = None

    # 类加() 触发 元类中的 __call__ 方法
    def __call__(cls, *args, **kwargs):
        # 类属性没赋值
        if not cls.instance:
            # 类属性 = 创建一个新的对象
            cls.instance = object.__new__(cls)
            # 对象.__init__ 初始化参数
            cls.instance.__init__(*args, **kwargs)
        # 类属性有值会返回相应的对象
        return cls.instance


class School(metaclass=MyMeta):
    def __init__(self, name):
        self.name = name

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


# 控制对象的产生,我们要重写 元类中 的 __call__
s = School(name='dream')
t = School(name='opp')

print(s.name)
print(t.name)

【七】单例模板

class SingletonType(type):
    def __init__(cls, name, bases, attrs):
        super(SingletonType, cls).__init__(name, bases, attrs)
        cls.instance = None

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


class Singleton(metaclass=SingletonType):
    pass

singleton_one = Singleton()
singleton_two = Singleton()

print(singleton_one)
# <__main__.Singleton object at 0x000001C0B531A770>
print(singleton_two)
# <__main__.Singleton object at 0x000001C0B531A770>
print(singleton_one is singleton_two)
# True

# 输出 True,表示是同一个实例

# # 使用 __call__ 方法获取单例
singleton_three = Singleton()
print(singleton_one is singleton_three)
# True