单例模式:确保类有且只有一个特定类型的对象,并提供全局访问点。
作用:程序运行过程中其实只有一个实例在运行;避免资源消耗及保证数据安全与全局性等。
场景:全局服务器配置;数据库连接;日志文件共享…
实现方式:
一. 模块
01.把函数与数据写入模块,实现单例对象
# singleton_by_module.py
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
02.使用时直接导入/单例模式对象=singleton_by_module.py
# test.py
from singleton_by_module import Singleton
t = Singleton()
二. 装饰器
# singleton_by_decorator.py
def Singleton(cls):
_instance = {
}
def _singleton(*args, **kwargs):
if cls not in _instance:
print('get ready init')
_instance[cls] = cls(*args, **kwargs)
print('get ready success')
else:
print('already init')
return _instance[cls]
return _singleton
@Singleton
class A(object):
def __init__(self, a=0):
self.a = a
a1 = A(1)
a2 = A(2)
print("a1_id:{},a1.a:{}".format(id(a1), a1.a))
print("a2_id:{},a2.a:{}".format(id(a1), a1.a))
01.程序运行:创建类对象a1调用,正常打印;当a1创建并调用由于实例已存在,调用a1,所以说他们的内存id一样。
三. 类
01.使用线程锁解决线程问题
import time
import threading
class Singleton:
_instance_lock = threading.Lock()
def __init__(self):
time.sleep(1)
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
def task(arg):
obj = Singleton.instance()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
time.sleep(20)
obj = Singleton.instance()
print(obj)
四.new方法
01.类实例前先执行new方法 ;然后执行init方法。
import threading
class Singleton:
_instance_lock = threading.Lock()
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = super(Singleton,cls).__new__(cls,*args, **kwargs)
return Singleton._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)
def task(arg):
obj = Singleton()
print(obj)
for i in range(5):
t = threading.Thread(target=task,args=[i,])
t.start()
五.metaclass元类
01.类由type创建,创建类时,type的init方法自动执行,类() 执行type的call方法(类的new方法,类的init方法)
02.对象由类创建,创建对象时,类的init方法自动执行,对象()执行类的call方法
import threading
class SingletonType(type):
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
with SingletonType._instance_lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
class Foo(metaclass=SingletonType):
def __init__(self,name):
self.name = name
obj1 = Foo('name')
obj2 = Foo('name')
print(obj1,obj2)
单例模式优缺点:
优点:全局只有一个实例,节省内存空间;避免开销;避免多重复用。
缺点:可扩展性差;违背单一原则;不利于测试。