第一阶段:Python开发基础 day30 面向对象高阶--单例模式

一、什么是单例模式

  • 单例模式:基于某种方法实例化多次得到实例是同一个

二、为什么用单例模式

  • 当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例

三、种方式实现单例模式

  • 第一种(通过类的绑定方法)

    dic = {'PORT':3306,'HOST':'127.0.0.1'}
    class Demo1():
        _instance = None
        def __init__(self,port,host):
            self.port = port
            self.host = host
    
        @classmethod
        def get_sigoleton(cls):
            if not cls._instance:
                cls._instance = cls(dic['PORT'],dic['HOST'])
            return cls._instance
    
    s1 = Demo1.get_sigoleton()
    s2 = Demo1.get_sigoleton()
    s3 = Demo1(33306,'192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    
  • 第二种(通过装饰器)

    • 用户输入端口和地址,实例化产生对象

    • 当用户不输入端口和地址,每次拿到的对象,都是同一个

    dic = {'PORT':3306,'HOST':'127.0.0.1'}
    def get_sigoleton(cls):
        _instance=None
        def wrapper(*args,**kwargs):
            if len(args)!=0 or len(kwargs)!=0:
                #表示传了参数,生成新对象
                res=cls(*args,**kwargs)
                return res
            else:
                nonlocal _instance
                if not _instance:
                    _instance=cls(dic['PORT'], dic['HOST'])
                return _instance
        return wrapper
    
    @get_sigoleton    #会把下面的Sql当中参数传入,相当于:Sql=get_sigoleton(Sql)
    class Sql():
        def __init__(self,port,host):
            self.port=port
            self.host=host
    s1=Sql()
    s2=Sql()
    s3=Sql('33306','192.168.1.1')
    s4=Sql('33306','192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    
  • 第三种(通过元类)

    • 当用户输入端口和地址,实例化产生新对象
    • 当用户不输入端口和地址,每次拿到的对象,都是同一个
    dicc = {'PORT':'3306','HOST':'127.0.0.1'}
    class Mymeta(type):
        def __init__(self,name,bases,dic):
            #self 是Sql类
    
            #把实例化好的对象,放到了类的名称空间
            self._instance=self(dicc['PORT'], dicc['HOST'])
        def __call__(self, *args, **kwargs):
            #self是谁?是Sql类
            if len(args)!=0 or len(kwargs)!=0:
                obj=object.__new__(self)
                obj.__init__(*args, **kwargs)
                return obj
            else:
                return self._instance
    
    class Sql(metaclass=Mymeta):    #相当于 Sql=Mymeta(name,bases,dic)   这个会调用 Mymeta的__init__  在里面已经向类的名称空间放了一个对象
        def __init__(self,port,host):
            self.port=port
            self.host=host
    
    print(Sql.__dict__)
    s1=Sql()
    #调用元类的__call__
    s2=Sql()
    s3=Sql('33306','192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    
  • 第四种(通过模块导入:python中的模块是天然的单例)

    def test():
        from sigonleton import s1
        print(s1.port)
        print(s1)
    def test2():
        from sigonleton import s1 as s2
        print(s2)
    
    test()
    test2()
    from sigonleton import s1
    from sigonleton import Sql
    s2=Sql(3306,'192.168.1.1')
    print(s1)
    print(s2)
    
    # 被调用的 sigonleton.py文件
    def test():
        from sigonleton import s1
        print(s1.port)
        print(s1)
    def test2():
        from sigonleton import s1 as s2
        print(s2)
    
    test()
    test2()
    from sigonleton import s1
    from sigonleton import Sql
    s2=Sql(3306,'192.168.1.1')
    print(s1)
    print(s2)
    

四、今日练习

https://www.cnblogs.com/foreversun92/p/11462013.html

原文地址:https://www.cnblogs.com/foreversun92/p/11462018.html