我有一个实现标准单例设计模式的类
ServerController
。每当该类在其起源的同一文件中实例化时 (main.py
),它都会按预期运行,并使用 ServerController
对象的第一个实例。但是,当我从另一个包含 get_ctrl()
的模块调用类的 getter 函数 main.py
时,尽管我采用单例设计模式,但仍会创建一个新实例。
这是我的单例实现:
class ServerController():
__instance = None
def __new__(cls):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
print("creating ctrl instance", cls.__instance)
return cls.__instance
pass
这是班级的
get_ctrl()
吸气功能:
@classmethod
def get_ctrl(cls):
if cls.__instance is None:
cls.__instance = ServerController()
return cls.__instance
在我的其他模块中,我调用
from main import ServerController
然后是
ctrl = ServerController.get_ctrl().
解决方案尝试1:
我也尝试过 functools 方法 但没有成功:
@classmethod
@functools.cache
def get_ctrl():
return ServerController()
解决方案尝试2:
除了上面显示的内容外,我还尝试了一个有点不同的
get_ctrl()
的实现:
@SingletonCache
@classmethod
def get_ctrl(cls):
return cls()
这伴随着
SingletonCache
课:
class SingletonCache:
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, cls):
if cls not in self.cache:
self.cache[cls] = self.func(cls)
return self.cache[cls]
这个方法给我读取的类型错误,
SingletonCache.__call__() missing 1 required positional argument: 'cls'
我也尝试过将
@classmethod
装饰器添加到 __call__(self, cls)
但没有成功。我愿意尝试任何允许我跨多个模块使用单个 ServerController
对象的方法。
感谢任何帮助。谢谢
对于
singleton pattern
,我认为最好的方法是使用metaclass
。
试试这个:
class SingletonMeta(type):
__instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls.__instances:
cls.__instances[cls] = super().__call__(*args, **kwargs)
return cls.__instances[cls]
class ServerController(metaclass=SingletonMeta):
@classmethod
def get_ctrl(cls, *args, **kwargs):
return cls(*args, **kwargs)
s1 = ServerController()
s2 = ServerController.get_ctrl()
print(s1)
print(s2)
print(s1 == s2)
<__main__.ServerController object at 0x00000269013ACD00>
<__main__.ServerController object at 0x00000269013ACD00>
True