• 单例模式的三种实现方式


    一、单例模式的三种实现方式

    1. 什么是单例模式

    • 基于某种方法,实例化多次,得到同一个实例/对象

    2. 为什么用单例模式

    • 实例化多次,得到的对象属性内容都一样时,应该将这些对象指向同一个内存,即同一个实例,来节省内存空间

    1. 实现单例模式方式一:类内部定义类方法实现

    • 实现方法:类中定义了一个类方法
    # 未单例模式前
    import setting
    class Mysql:
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
        @classmethod
        def from_conf(cls):
            return cls(setting.IP,setting.PORT)
    
    obj1=Mysql.from_conf()
    obj2=Mysql.from_conf()
    obj3=Mysql.from_conf()
    
    # 内容相同
    print(obj1.__dict__)
    print(obj2.__dict__)
    print(obj3.__dict__)
    # 但是占用不同的内存空间,导致内存空间浪费
    print(obj1)
    print(obj2)
    print(obj3)
    ----------------------------------------------------
    {'ip': '10.0.0.1', 'port': 3306}
    {'ip': '10.0.0.1', 'port': 3306}
    {'ip': '10.0.0.1', 'port': 3306}
    <__main__.Mysql object at 0x000001B0F234F588>
    <__main__.Mysql object at 0x000001B0F234F5F8>
    <__main__.Mysql object at 0x000001B0F234F630>
    
    # setting配置文件
    IP='10.0.0.1'
    PORT=3306
    
    import setting
    class Mysql:
        # 先定义一个变量,用于接收对象
        __instance=None
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
        @classmethod
        def from_conf(cls):
            # 如果没有实例化过,就重新实例化,如果有就返回实例化过的对象
            if cls.__instance is None:
                cls.__instance=cls(setting.IP,setting.PORT)
            return cls.__instance
    
    obj1=Mysql.from_conf()
    obj2=Mysql.from_conf()
    obj3=Mysql.from_conf()
    
    # 内容相同
    print(obj1.__dict__)
    print(obj2.__dict__)
    print(obj3.__dict__)
    # 占用相同的内存空间
    print(obj1)
    print(obj2)
    print(obj3)
    ---------------------------------------------------------------
    {'ip': '10.0.0.1', 'port': 3306}
    {'ip': '10.0.0.1', 'port': 3306}
    {'ip': '10.0.0.1', 'port': 3306}
    <__main__.Mysql object at 0x000001A79D29F588>
    <__main__.Mysql object at 0x000001A79D29F588>
    <__main__.Mysql object at 0x000001A79D29F588>
    
    # 如果ip,port不同,再单独造对象
    obj4=Mysql('10.0.0.10',3307)
    print(obj4)
    print(obj4.__dict__)
    ---------------------------------------------------------------
    <__main__.Mysql object at 0x0000015D8C13F630>
    {'ip': '10.0.0.10', 'port': 3307}
    

    2. 实现单例模式方式二:利用装饰器实现

    • _intance是一种命名习惯,代表在函数内使用的名字
    import setting
    def singleton(cls):
        _intance=cls(setting.IP,setting.PORT)
        def wrapper(*args,**kwargs):
            if len(args) == 0 and len(kwargs) == 0:
                return _intance
            return cls(*args,**kwargs)
        return wrapper
    
    @singleton # Mysql=singleton(Mysql)  Mysql=wrapper
    class Mysql:
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
    obj1=Mysql()  # wrapper()
    obj2=Mysql()
    obj3=Mysql()
    print(obj1 is obj2 is obj3)
    
    print(obj1)
    print(obj2)
    print(obj3)
    -----------------------------------------------------
    True
    <__main__.Mysql object at 0x000001ED9FBDF588>
    <__main__.Mysql object at 0x000001ED9FBDF588>
    <__main__.Mysql object at 0x000001ED9FBDF588>
    

    3. 实现单例模式方式三:定制元类实现

    import setting
    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic): # self=Mysql
            super().__init__(class_name,class_bases,class_dic)
            # 创造一个Mysql的空对象
            self.__instance=self.__new__(self)
            # 从配置文件中获取信息,初始化Mysql的对象
            self.__init__(self.__instance,setting.IP,setting.PORT)
    
        def __call__(self, *args, **kwargs):   # self=Mysql
            if len(args) == 0 and len(kwargs) == 0:
                return self.__instance   # 返回的是一个已经创建好的Mysql对象
            # 如果在Myql()括号内,单独传入内容,再重新造对象
            obj=self.__new__(self)
            self.__init__(self,*args,**kwargs)
            return obj
    
    class Mysql(object,metaclass=Mymeta):
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
    obj1=Mysql()
    obj2=Mysql()
    obj3=Mysql()
    obj4=Mysql('10.0.0.10',3307)
    
    print(obj1)
    print(obj2)
    print(obj3)
    print(obj4)
    --------------------------------------------------------------------------
    <__main__.Mysql object at 0x0000021DBB7FF668>
    <__main__.Mysql object at 0x0000021DBB7FF668>
    <__main__.Mysql object at 0x0000021DBB7FF668>
    
    <__main__.Mysql object at 0x0000021DBB7FF6A0>
    
  • 相关阅读:
    BOM-Window窗口对象
    BOM
    案例:电灯开关
    事件简单学习
    简单学习
    ECMAScript基本对象——Global全局对象
    ECMAScript基本对象——RegExp 正则表达式对象
    ECMAScript基本对象——String 对象
    zk安装管理
    kafka服务器批量copy文件脚本
  • 原文地址:https://www.cnblogs.com/itone/p/9253629.html
Copyright © 2020-2023  润新知