Python设计模式之单例模式丨【生长吧!Python】

举报
lwq1228 发表于 2021/07/09 17:23:05 2021/07/09
【摘要】 Python设计模式之单例模式

1、什么是单例模式

确保一个类只有一个实例,并且提供一个访问它的全局方法。

2、单例模式设计思想

单例模式就是保证一个类有且只有一个对象(实例)的一种机制。单例模式用来控制某些事物只允许有一个个体。

3、单例模式的模型抽象

3.1、代码框架

单例模式的实现方式有很多种,下面列出几种常见的方式。

3.1.1、重写__new__和__init__方法

1、代码

class Singleton(object):
    """单例实现方式一"""
    __instance = None
    __isFirstInit = False

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

    def __init__(self, name):
        if not self.__isFirstInit:
            self.__name = name
            Singleton.__isFirstInit = True

    def getName(self):
        return self.__name
# Test
tony = Singleton("Tony")
karry = Singleton("Karry")
print(tony.getName(), karry.getName())
print("id(tony):", id(tony), "id(karry):", id(karry))
print("tony == karry: ", tony == karry)

2、输出结果

Tony Tony
id(tony): 2448374521616 id(karry): 2448374521616
tony == karry:  True

3、说明

1、在Python 3的类中,__new__负责对象的创建,而__init__负责对象的初始化;__new__是一个类方法,而__init__是一个对象方法。
2、__new__是我们通过类名进行实例化对象时自动调用的,__init__是在每一次实例化对象之后调用的,__new__方法创建一个实例之后返回这个实例的对象,并将其传递给__init__方法的self参数。
3、在上面的示例代码中,我们定义了一个静态的__instance 类变量,用来存放Singleton的对象,__new__方法每次返回同一个__instance 对象(若未初始化,则进行初始化)。因为每一次通过 s=Singleton()的方式创建对象时,都会自动调用__init__方法来初始化实例对象,因此__isFirstInit 的作用就是确保只对__instance 对象进行一次初始化。

3.1.2、自定义metaclass的方法

1、代码

class Singleton(type):
    """单例实现方式二"""

    def __init__(cls, what, bases=None, dict=None):
        super().__init__(what, bases, dict)
        # 初始化全局变量cls._instance为 None
        cls._instance = None

    def __call__(cls, *args, **kwargs):
        # 控制对象的创建过程,如果cls._instance为 None,则创建,否则直接返回
        if cls._instance is None:
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance
class CustomClass(metaclass=Singleton):
    """用户自定义的类"""

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name
tony = CustomClass("Tony")
karry = CustomClass("Karry")
print(tony.getName(), karry.getName())
print("id(tony):", id(tony), "id(karry): ", id(karry))
print("tony == karry: ", tony == karry)

2、输出结果

Tony Tony
id(tony): 2172407274992 id(karry):  2172407274992
tony == karry:  True

3、说明

在上面的代码中,我们定义了metaclass(Singleton)来控制对象的实例化过程。
在定义自己的类时,我们通过 class CustomClass(metaclass=Singleton)来显式地指定 metaclass 为Singleton。

3.1.3、装饰器的方法

1、代码

def singletonDecorator(cls, *args, **kwargs):
    """定义一个单例装饰器"""
    instance = {}

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

    return wrapperSingleton
@singletonDecorator
class Singleton:
    """使用单例装饰器修饰一个类"""

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name
tony = Singleton("Tony")
karry = Singleton("Karry")
print(tony.getName(), karry.getName())
print("id(tony):", id(tony), "id(karry): ", id(karry))
print("tony == karry: ", tony == karry)

2、输出结果

Tony Tony
id(tony): 2975555472736 id(karry):  2975555472736
tony == karry:  True

3、说明

装饰器的实质就是对传进来的参数进行补充,可以在不对原有的类做任何代码变动的前提下增加额外的功能,使用装饰器可以装饰多个类。
用装饰器的方式来实现单例模式,通用性非常高,在实际项目中用得非常多。

3.2、类图

类图非常简单,只有一个类,类中只有一个方法,getInstance()的作用就是获取该类的唯一实例。

【生长吧!Python】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/278897

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。