这是依赖注入和/或Singleton模式吗



TL;DR:如果注入的对象是Singleton,那么依赖注入和Singleton模式之间有什么区别?

对于如何解决我目前面临的设计问题,我得到了喜忧参半的结果。

我希望有一个应用程序范围的配置,以便不同的对象和更改配置。

我想使用Singleton:来解决这个问题

class ConfigMeta(type):
_instance = None
def __call__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__call__(*args, **kwargs)
return cls._instance

class Config(metaclass=ConfigMeta):
def __init__(self) -> None:
pass

但搜索已经表明,这很容易出错,并且被认为是不好的做法(在管理类状态时(。几乎所有其他帖子都建议使用依赖注入,但他们让我困惑于他们是如何做到的。他们都说"你的实现可以是Singleton,但将它注入到他们构造函数中的其他对象中"。

这将是一种类似于的东西

# foo.py
from config import Config
class Foo:
def __init__(self):
self.config = Config()
# bar.py
from config import Config
class Bar:
def __init__(self):
self.config = Config()

然而,这些self.config中的每一个都引用相同的实例。因此我感到困惑。。。

这是如何被视为依赖注入而不是Singleton模式的?

如果它被认为是依赖注入,那么它只是Singleton模式会是什么样子?

通过依赖注入(DI(,您可以将其留给DI系统来解决如何获得特定对象。你只需要声明你需要什么样的对象。这是对Singleton模式的补充,其中整个应用程序由特定类型的单个实例提供服务。例如:

class Config:
pass
config = Config()  # singleton
class Foo:
def __init__(self):
config = config

这里,Foo类处理如何获取Config对象本身的逻辑。假设这个对象本身有依赖项,那么它也需要由Foo进行排序。

另一方面,依赖注入有一个中央单元来处理这类事情。用户类只是声明它需要什么对象。例如:

class DI:
config = Config()
@classmethod
def get_config_singleton(cls):
return cls.config
@classmethod
def get_config(cls):
return Config()
@classmethod
def inject(cls, func):
from functools import partialmethod
# The DI system chooses what to use here:
return partialmethod(func, config=cls.get_config())

class Foo:
@DI.inject  # it's up to the DI system to resolve the declared dependencies
def __init__(self, config: Config):  # declare one dependency `config`
self.config = config

依赖注入意味着为构造函数提供初始化的对象,在本例中为config

问题中的代码没有使用依赖注入,因为构造函数__init__没有接收作为参数的config,所以这里只使用singleton模式。

请在此处查看有关Python中依赖项注入的更多信息。

最新更新