5种单例模式

单例模式:
    是一个软件的设计模式,为了保证一个类,无论调用多少次产生的实例对象,都是指向同一个内存地址,仅仅只有一个实例对象。
5种单例模式:
    -模块
    -装饰器
        通过调用类方法实例对象时,自动触发__new__来实现
    -元类
    -__new__
        通过调用类方法实例对象时,自动触发__new__来实现
    -类方法:classmethod
# 1.模块:
import cls_singleton

s1=cls_singleton.instance
s2=cls_singleton.instance

print(s1 is s2)#True

# 2.装饰器
def singleton_wrapper(cls):
    _singleton={

    }
    def inner(*args,**kwargs):
        if cls not in _singleton:
            _singleton[cls]=cls(*args,**kwargs)
            return _singleton[cls]

    return inner


@singleton_wrapper
class Too(object):
    pass


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

# 3.元类
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')

# 4.__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()


# 5.类方法:@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('tank', '123')
obj2 = Foo.singleton('tank', '123')

猜你喜欢

转载自www.cnblogs.com/lqb666/p/12890245.html