实现单例的四种方法

1. 储备知识

# 储备知识
#4 、自定义元类:
class Mymeta(type):
    # 来控制类Foo的创建
    def __init__(self,class_name,class_bases,class_dic): #self=Foo

        if not class_name.istitle():
            raise TypeError('类名的首字母必须大写傻叉')

        if not class_dic.get('__doc__'):
            raise TypeError('类中必须写好文档注释,大傻叉')

        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
#
    # 控制类Foo的调用过程,即控制实例化Foo的过程
    def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}

        #1 造一个空对象obj
        obj=object.__new__(self)

        #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
        self.__init__(obj,*args,**kwargs)

        return obj

·····························

# 单例:所有实例化出来的对象都是同一个

# 所有的配置信息放在一个类中,拿配置文件就实例化类的对象就行
# (问题是每次拿到的对象虽然一样,但内存地址不同,就用到了单例)

# 第一种 基于__new__的单例
# 通过使用__new__来控制实例的创建过程

# 实例化对象的的过程:1.先产生一个空对象(__new__),然后在调用init方法
class Singleton(object):
    __instance = None
    def __new__(cls,*args,**kwargs):
        if not cls.__instance:
            # 实际object.__new__(self)返回的就是一个对象
            cls.__instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
        return cls.__instance

a1 = Singleton()
a2 = Singleton()
# 第二种:基于模块的单例模式(用来导入的时候) # 原因:第一次调用模块时,执行一遍,第二次以后调用都不执行(模块调用只执行一次) class Settings(object): x = 100 def foo(self): print("foo") settings = Settings() # 另一个py文件中调用这个模块 # from funcs import settings (这样内存中就有了settings对象,以后用的都是一个了,实现了单例) # 第三种 # 思路: 定义一个类(__instance = None),在类中定义一个类方法 singleton(cls),如果__instance为空,则创建对象 import settings class MySQL(object): __instance = None def __init__(self,ip,port): self.ip = ip self.port = port # 可以保证只有一个对象,但还是可以通过调用类产生新对象(解决:用元类来控制实例化的过程__call__) @classmethod def singleton(cls): if not cls.__instance: # 创建对象 obj = cls(settings.IP,settings.PORT) cls.__instance = obj return cls.__instance obj4=MySQL.singleton() obj5=MySQL.singleton() # id 相同 # 以上参数为配置文件中同一套参数,实现了单例

# 第四种方式,利用元类来实现单例 # 调用类产生对象,实际是调用原类中的__call__方法,自定义__call__方法 # 定义元类 class MyMeta(type): __instance = None # 控制类Foo的调用过程,即控制实例化Foo的过程 def __call__(self, *args, **kwargs): if not MyMeta.__instance: __instance = object.__new__(self) self.__init__(__instance,*args,**kwargs) MyMeta.__instance = __instance return MyMeta.__instance class Printer(metaclass = MyMeta): print(1111) p1 = Printer() p2 = Printer() # id 地址一样

猜你喜欢

转载自www.cnblogs.com/Afrafre/p/10384792.html