• 单例模式


    一、什么是单例模式


    整个过程中只有一个实例,所有生成的实例都指向同一块内存空间,本质是为了节省空间

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    p1 = Person('yjy',18)
    p2 = Person('yjy',18)
    print(p1)  #<__main__.Person object at 0x000002694B07E278>
    print(p2)  #<__main__.Person object at 0x000002694B07E2B0>

    以上p1和p2的内存空间不一样,就不是单例模式

    二、实现单例模式的方法


    需求:

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

    2.1 通过类的绑定方法

    class Sql():  #定义一个Sql类
        _instance = None   #定义一个初始变量__instance=None,将第一次实例的对象传给他,有每次外面再访问就直接进行get_singleton里面的if判断
        def __init__(self,port,host):
            self.port = port
            self.host = host
        @classmethod   #运用类的绑定方法  绑定给Sql类去直接调用实例化
        def get_singleton(cls):   #cls为Sql
            # 目的是要调取Sql这个类通过从配置文件读取IP、端口参数,完成调用init方法,拿到一个实例化init方法的对象
            import settings     #导入模块
            if not cls._instance:    #如果_instance这个方法不在在类的名称空间里面
                cls._instance = cls(settings.PORT,settings.HOST)   #返回我们在settings里面设置好的端口号和主机号的内存地址
            return cls._instance   #返回这个属性的名称空间  其实就是return cls(settings.IP,settings.PORT)
    
    #每次调用get_singleton 拿到的对象都是同一个
    s1 = Sql.get_singleton()  #<__main__.Sql object at 0x000001BF2DCEECC0>
    s2 = Sql.get_singleton()  #<__main__.Sql object at 0x000001BF2DCEECC0>
    print(s1)
    print(s2)
    s3 = Sql('33306','192.168.1.1')  #重新去实例化一个东西   #Sql(ip,port)  就是调用Sql里面的init方法
    print(s3)   #<__main__.Sql object at 0x000001BF2DCEECF8>
    #模板
    class Sql():  
        _instance = None  
        def __init__(self,port,host):
            self.port = port
            self.host = host
        @classmethod   
        def get_singleton(cls):  
            import settings     
            if not cls._instance:   
                cls._instance = cls(settings.PORT,settings.HOST)   
            return cls._instance   
    s1 = Sql.get_singleton()  
    s2 = Sql.get_singleton()  
    print(s1)
    print(s2)
    s3 = Sql('33306','192.168.1.1')  
    print(s3) 

    2.2 通过装饰器

    import settings
    def get_singleton(cls):
        _instance = cls(settings.PORT,settings.HOST)  #给Sql的init方法传参,实例化得到一个对象,__instance
        def wrapper(*args,**kwargs):  #判断外面调用时是否有传值进来
            if len(args) ==0 and len(kwargs) == 0:   # 用户没有传参,
                return _instance  #直接返回默认settings的值
            return cls(*args,**kwargs)  #有用户传参,生成新对象,创建新的值,产生新的名称空间
        return wrapper
    
    @get_singleton  #会把下面的Sql当中参数传入,相当于:Sql=get_sigoleton(Sql)
    class Sql():   #Sql= singleton(Sql)   Sql = wrapper
        def __init__(self,port,host):
            self.port = port
            self.host = host
    
    Sql = get_singleton(Sql)
    s1 = Sql()
    s2 = Sql()
    print(s1)  #<__main__.Sql object at 0x00000188E00BE940>
    print(s2)  #<__main__.Sql object at 0x00000188E00BE940>
    s3 = Sql('3306','192.168.1.2')
    print(s3)  #<__main__.Sql object at 0x00000188E00BECC0>
    #模板
    import settings
    def get_singleton(cls):
        _instance = cls(settings.PORT,settings.HOST)
        def wrapper(*args,**kwargs):
            if len(args) ==0 and len(kwargs) == 0:
                return _instance
            return cls(*args,**kwargs)
        return wrapper
    
    @get_singleton
    class Sql():
        def __init__(self,port,host):
            self.port = port
            self.host = host
    
    Sql = get_singleton(Sql)
    s1 = Sql()
    s2 = Sql()
    print(s1)
    print(s2)
    s3 = Sql('3306','192.168.1.2')
    print(s3)

    2.3 通过元类

    import settings
    class Mymeta(type):
        def __init__(self,name,bases,dic):  #self是Sql类  造Sql的空对象
            self._instance = self(settings.PORT,settings.HOST)  #为空对象初始化独有的属性
        def __call__(self, *args, **kwargs):  #self是Sql类  在调用类时创建
            if len(args) == 0 and len(kwargs) == 0:  #如果没有传参
                    return self._instance  #返回给空对象初始化好的属性
            obj = object.__new__(self)  #类的实例化产生一个新的对象用obj接收
            obj.__init__(*args, **kwargs)  #初始化新的obj对象
            return obj  #已经创建好的Sql对象
    
    class Sql(metaclass=Mymeta):
        def __init__(self,port,host):
            self.port = port
            self.host = host
    
    s1 = Sql()   #触发自定义类的__init__
    s2 = Sql()
    print(s1)  #<__main__.Sql object at 0x00000224460BECF8>
    print(s2)  #<__main__.Sql object at 0x00000224460BECF8>
    s3 = Sql('3306','192.168.1.2')
    print(s3)  #<__main__.Sql object at 0x000002244D0CC6A0>
    #模板
    import settings
    class Mymeta(type):
        def __init__(self,name,bases,dic):  #self是Sql类
            self._instance = self(settings.PORT,settings.HOST)
        def __call__(self, *args, **kwargs):  #self是Sql类
            if len(args) == 0 and len(kwargs) == 0:
                    return self._instance
            obj = object.__new__(self)
            obj.__init__(*args, **kwargs)
            return obj
    
    class Sql(metaclass=Mymeta):
        def __init__(self,port,host):
            self.port = port
            self.host = host
    
    s1 = Sql()
    s2 = Sql()
    print(s1)
    print(s2)
    s3 = Sql('3306','192.168.1.2')
    print(s3)

    2.4 导入模块实现(Python的模块是天然的单例)

    '''配置文件settings'''
    PORT = 3306
    HOST = '127.0.0.1'
    
    
    '''模块文件singleton'''
    import settings
    class Sql():
        def __init__(self,port,host):
            self.port=port
            self.host=host
    s1=Sql(settings.PORT,settings.HOST)
    
    
    '''执行文件'''
    #方式一
    def test():
        from singleton import s1
        print(s1)  #这个s1和下面的s1不是一个,但是值相同
    
    def test2():
        from singleton import s1,Sql
        print(s1)  #这个s1和上面的s1不是一个,但是值相同
        obj = Sql(3306,'192.168.1.1')  #传参的时候生成一个新的空对象
        print(obj)  #打印传进去的对象
    
    test()   #<singleton.Sql object at 0x000001D73F0AD198>
    test2()   #<singleton.Sql object at 0x000001D73F0AD198>
    s3=(3308,'192.168.1.1')  #<singleton.Sql object at 0x000001B0F4FEE160>
    
    
    #方式二
    def test():
        from singleton import s1
        print(s1)
    
    def test2():
        from singleton import s1 as s2
        print(s2)
    
    test()  #print(s1) <singleton.Sql object at 0x000001F578752630>
    test2()  #print(s2) <singleton.Sql object at 0x000001F578752630>  #不传参s1和s2一样
    from singleton import s1   #不传参就用原来定义好的对象
    from singleton import Sql  
    s3=Sql(3306,'192.168.1.1')   #传参的时候生成新的空对象
    print(s3)  #<singleton.Sql object at 0x000001F57172E128>
     
  • 相关阅读:
    C#基础知识之静态和非静态
    C#基础知识之类和结构
    jQuery选择器
    ajax和json的优缺点
    说几条JavaScript的基本规范
    vue中异步请求渲染问题(swiper不轮播)(在开发过程中遇到过什么问题、踩过的坑)
    vue响应数据的原理
    面向对象的几种方式(创建对象的几种方式)
    ES6新特性
    HTML和XHTML的区别
  • 原文地址:https://www.cnblogs.com/lulingjie/p/11529017.html
Copyright © 2020-2023  润新知