ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python实现单例模式

2022-09-09 01:01:33  阅读:211  来源: 互联网

标签:__ python args 模式 instance 单例 kwargs cls


一、什么是单例模式?

"""
单例模式:
    单例模式是一个软件的设计模式,为了保证一个类,无论调用多少次产生的实例对象,
    都是指向同一个内存地址,仅仅只有一个实例(对象)!

    五种单例:
        - 模块
        - 装饰器
        - 元类
        - __new__
        - 类方法: classmethod
"""

二、单例模式的实现

1.通过类方法实现单例模式

'''
方式一: @classmethod  ---> 通过类方法来实现单例
'''


class Foo(object):
    # 定义了一个类的数据属性,
    # 用于接收对象的实例,判断对象的实例是否只有一个
    _instance = None  # obj1

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

    @classmethod
    def singleton(cls, *args, **kwargs):
        # 判断类属性_instance是否有值,有代表已经有实例对象
        # 没有则代表没有实例对象,则调用object的__init__获取实例对象
        if not cls._instance:
            # object.__new__(cls): 创造对象
            # 没有参数情况下
            # cls._instance = object.__new__(cls, *args, **kwargs)

            # 有参数的情况下
            cls._instance = cls(*args, **kwargs)  # 相当于Foo()

        # 将已经产生的实例对象  直接返回
        return cls._instance


obj1 = Foo.singleton('yessir', '123')
obj2 = Foo.singleton('yessir', '123')
# print(obj1 is obj2)

2.通过元类实现单例模式

'''
方式二: 元类
'''


class MyMeta(type):

    # 1、先触发元类里面的__init__
    def __init__(self, name, base, attrs):  # self --> Goo
        # *** 造空的对象, 然后赋值给了Goo类中的_instance类属性
        self._instance = object.__new__(self)
        # 将类名、基类、类的名称空间,传给type里面的__init__
        super().__init__(name, base, attrs)
        # type.__init__(self, name, base, attrs)

    # 2、当调用Goo类时,等同于调用了由元类实例化的到的对象
    def __call__(self, *args, **kwargs):
        # 判断调用Goo时是否传参
        if args or kwargs:
            init_args = args
            init_kwargs = kwargs

            # 1)通过判断限制了用于传入的参数必须一致,然后返回同一个对象实例
            if init_args == args and init_kwargs == kwargs:
                return self._instance

            # 2) 若不是同一个实例,则新建一个对象,产生新的内存地址
            obj = object.__new__(self)
            self.__init__(obj, *args, **kwargs)
            return obj

        return self._instance


class Goo(metaclass=MyMeta):  # Goo = MyMeta(Goo)
    # _instance = obj
    def __init__(self, x):
        self.x = x


g1 = Goo('1')
g2 = Goo('1')
# print(g1 is g2)  # True

3.通过__new__方法实现单例模式

'''
方式三: __new__实现   ---> 通过调用类方法实例化对象时,自动触发的__new__来实现单例
'''


class Aoo(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)

        return cls._instance


a1 = Aoo()
a2 = Aoo()
# print(a1 is a2)  # True

4.通过装饰器实现单例模式

'''
方式四: 装饰器实现     ---> 通过调用类方法实例化对象时,自动触发的__new__来实现单例
'''


# 单例装饰器
def singleton_wrapper(cls):  # cls ---> Too
    # 因为装饰器可以给多个类使用,所以这里采用字典
    # 以类作为key, 实例对象作为value值
    _instance = {
        # 伪代码: 'Too': Too的示例对象
    }

    def inner(*args, **kwargs):
        # 若当前装饰的类不在字典中,则实例化新类
        # 判断当前装饰的Too类是否在字典中
        if cls not in _instance:
            # obj = cls(*args, **kwargs)
            # return obj
            # 不在,则给字典添加 key为Too, value为Too()---> 实例对象
            # {Too: Too(*args, **kwargs)}
            _instance[cls] = cls(*args, **kwargs)

        # return 对应的实例对象cls(*args, **kwargs)
        return _instance[cls]

    return inner


@singleton_wrapper  # singleton_wrapper(Too)
class Too(object):
    pass


t1 = Too()
t2 = Too()
# print(t1 is t2)  # True

5.通过模块导入实现单例

'''
方式五: 模块导入实现

模块导入是天然的单例,也是最简单容易实现的一种方式
'''
import cls_singleton

s1 = cls_singleton.instance
s2 = cls_singleton.instance

print(s1 is s2)  # True

 

标签:__,python,args,模式,instance,单例,kwargs,cls
来源: https://www.cnblogs.com/yesirya/p/16671315.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有