一、单例模式
单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费!!!
二、实现
1. 适用模块
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc
文件,当第二次导入时,就会直接加载 .pyc
文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
2. 装饰器
# -*- coding: utf-8 -*- def singleton(cls): instances = {} def getinstance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return getinstance @singleton class MyClass(object): a = 1 if __name__ == '__main__': a = MyClass() b = MyClass() print(a, b) b.a = 4 print(a.a, b.a)
3. __new__() (线程同步)
# -*- coding: utf-8 -*- # https://www.jb51.net/article/135156.htm import threading class Singleton(object): _instance_lock = threading.Lock() def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): with cls._instance_lock: if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance if __name__ == '__main__': obj1 = Singleton() obj2 = Singleton() print(obj1, obj2) def task(arg): obj = Singleton() print(obj) for i in range(10): t = threading.Thread(target=task, args=[i, ]) t.start()
4. metaclass
# -*- coding: utf-8 -*- import threading class SingletonMetaclass(type): _instance_lock = threading.Lock() def __call__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): with cls._instance_lock: if not hasattr(cls, '_instance'): cls._instance = super(SingletonMetaclass, cls).__call__(cls, *args, **kwargs) return cls._instance class Foo(metaclass=SingletonMetaclass): def __init__(self, name): self.name = name if __name__ == '__main__': obj1 = Foo() obj2 = Foo() print(obj1, obj2) def task(arg): obj = Foo() print(obj) for i in range(10): t = threading.Thread(target=task, args=[i, ]) t.start()