目录

  • 一、什么是单例模式
  • 二、为什么用单例模式
  • 三、单例模式(类内部定义静态方法)
  • 四、单例模式(装饰器)
  • 五、单例模式(元类)


一、什么是单例模式
  • 单例模式:基于某种方法实例化多次得到实例是同一个
二、为什么用单例模式
  • 当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例

面向对象高级实战之单例模式_面向对象

三、单例模式(类内部定义静态方法)
# settings.py
IP = '1.1.1.1'
PORT = 3306


class Mysql:
    __instacne = None

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def from_conf(cls):
        if cls.__instacne is None:
            cls.__instacne = cls(IP, PORT)
        return cls.__instacne


obj1 = Mysql.from_conf()
obj2 = Mysql.from_conf()
obj3 = Mysql.from_conf()
print(obj1 is obj2 is obj3)
True
print(obj1.__dict__)
print(obj2.__dict__)
print(obj3.__dict__)
{'ip': '1.1.1.1', 'port': 3306}
{'ip': '1.1.1.1', 'port': 3306}
{'ip': '1.1.1.1', 'port': 3306}
obj4 = Mysql('10.10.10.11', 3307)
print(obj4.__dict__)
{'ip': '10.10.10.11', 'port': 3307}
四、单例模式(装饰器)
# settings.py
IP = '1.1.1.1'
PORT = 3306


def singleton(cls):
    cls.__instance = cls(IP, PORT)

    def wrapper(*args, **kwargs):
        if len(args) == 0 and len(kwargs) == 0:
            return cls.__instance
        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()  # wrapper()
obj3 = Mysql()  # wrapper()
print(obj1 is obj2 is obj3)
True
print(obj1.__dict__)
print(obj2.__dict__)
print(obj3.__dict__)
{'ip': '1.1.1.1', 'port': 3306}
{'ip': '1.1.1.1', 'port': 3306}
{'ip': '1.1.1.1', 'port': 3306}
obj4 = Mysql('1.1.1.4', 3308)
print(obj4.__dict__)
{'ip': '1.1.1.4', 'port': 3308}
五、单例模式(元类)
# settings.py
IP = '1.1.1.1'
PORT = 3306


class Mymeta(type):
    def __init__(self, class_name, class_bases, class_dic):  # self = Mysql
        super(Mymeta, self).__init__(class_name, class_bases, class_dic)
        
        # 完成Mysql对象的初始化
        self.__instance = self.__new__(self)  # 造出一个Mysql的对象
        self.__init__(self.__instance, IP, PORT)  # 从配置文件中加载配置完成Mysql对象的初始化

        print(self.__instance)
        print(self.__instance.__dict__)

    def __call__(self, *args, **kwargs):  # self = Mysql
        if len(args) == 0 and len(kwargs) == 0:
            return self.__instance

        obj = self.__new__(self)
        self.__init__(obj, *args, **kwargs)

        return obj


class Mysql(object, metaclass=Mymeta):  # Mysql = Mymeta(...)
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


obj1 = Mysql()
obj2 = Mysql()
obj3 = Mysql()
<__main__.Mysql object at 0x10c7f1f98>
{'ip': '1.1.1.1', 'port': 3306}
print(obj1 is obj2 is obj3)
True
print(obj1.__dict__)
print(obj2.__dict__)
print(obj3.__dict__)
{'ip': '1.1.1.1', 'port': 3306}
{'ip': '1.1.1.1', 'port': 3306}
{'ip': '1.1.1.1', 'port': 3306}
obj4 = Mysql('10.10.10.11', 3308)

print(obj4.__dict__)
{'ip': '10.10.10.11', 'port': 3308}
print(Mysql.__dict__)
{'__module__': '__main__', '__init__': <function Mysql.__init__ at 0x10c6b1d90>, '__dict__': <attribute '__dict__' of 'Mysql' objects>, '__weakref__': <attribute '__weakref__' of 'Mysql' objects>, '__doc__': None, '_Mymeta__instance': <__main__.Mysql object at 0x10c7f1f98>}

面向对象高级实战之单例模式_面向对象_02