单例模式介绍及python实现
简介
在众多设计模式中。对于同一个类,始终提供一个对象,保证提供的对象只有一个,适用于需要频繁进行初始化操作 例如单个数据库的频繁读写操作、多线程操作同一个文件时也需要保证是同一个实例。
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式的python实现
装饰器
使用类变量,一个字典存储唯一的一个实例化对象,当字典为空时则代表对象为空,创建一个对象,否则直接返回字典中的实例化对象。
from functools import wraps
def singleton(cls):
instance = {}
@wraps(cls)
def inner(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return inner
@singleton
class Test(object):
def __init__(self) -> None:
pass
t1 = Test()
print(id(t1))
t2 = Test()
print(id(t2))
print(t1 == t2)
1461434937120
1461434937120
True
使用基类
由于实例化对象的动作归根结带底是__new__
方法返回实例化对象,__init__
只是返回__new__
的结构,因此重写__new__
方法即可,需要注意的是__new__
是类方法。
class Singleon(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super(Singleon, cls).__new__(cls, *args, **kwargs)
return cls._instance
class Test(Singleon):
def __init__(self) -> None:
super().__init__()
t1 = Test()
print(id(t1))
t2 = Test()
print(id(t2))
print(t1 == t2)
1751642104896
1751642104896
True
使用元类
由于type是所有类的默认元类,且当类()会调用type的__call__
方法,因此只需要重写type的__call__
方法即可
from typing import Any
class Singleon(type):
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
if not hasattr(cls, "_instance"):
cls._instance = super().__call__(*args, **kwargs)
return cls._instance
class Test(metaclass=Singleon):
def __init__(self) -> None:
pass
t1 = Test()
print(id(t1))
t2 = Test()
print(id(t2))
print(t1 == t2)