DI容器 vs. 工厂模式

4

我知道有很多关于依赖注入的文章和线程,但关于依赖注入容器的文章相对较少。我发现Fabien Potencier撰写的这篇文章非常有用,尽管它是针对PHP的。然而,当我阅读更多关于这些容器的内容时,我得出的结论是这只不过是一个简单的工厂方法集合,这是真的吗?

深入且更具体的看法: 将一个依赖项注入到对象中时

foo.Bar = new Dependency();

我也可以写

foo.Bar = new myFactory.CreateDependency();

或者使用容器。
foo.Bar = myContainer.CreateDependency();

在最后一种方法中,容器不仅有一个方法可以创建其他类型,而是有许多其他方法,因此它只是用于工厂方法的容器,对吗?

4个回答

3
整个 DI 容器的意义在于你永远不需要/也不应该编写像这样的代码
foo.Bar = myContainer.CreateDependency();

这被认为是反模式。 DI容器应该仅在组合根(即主要DI容器使用模式)中使用一次。

DI容器会根据配置自动构建对象并通过构造函数或属性注入依赖项。在工厂的情况下,您必须自己完成所有操作。除了创建之外,DI容器还提供以下功能:

生命周期管理。因此,每当需要依赖关系时,容器可能会注入相同的对象(单例生命周期),或者每次返回新对象。

有限的AOP功能,例如方法调用拦截以及在方法之前和之后执行自定义逻辑。

您可以查看这本书 .NET中的依赖注入。它帮助我了解DI容器、使用模式和依赖注入的概念。


但是容器如何知道何时构造任何类的新实例? - MakePeaceGreatAgain
当然,应该明确调用 DI 容器,并且这应该在某个“入口点”完成。例如,在 Web 应用程序中,这个入口点是创建控制器的地方,其中调用了 resolve 方法:container.Resolve<ISomeController>。但是 SomeController 本身并不知道 DI 容器被使用了。这就是组合根模式的本质。 - wunzsh

2
您可以将DI容器/库视为一个具有许多高级对象构造方法(通过反射)的工厂框架。这很有用,因为通常您不必编写任何高级方法,例如加载插件程序集并获取插件数据类型。但缺点是反射速度较慢,最好在应用程序初始化阶段使用它。但是,如果您想在运行时使用它创建大量小对象,它会减慢您的速度。
另一方面,您自己的工厂是定制的,并且通常包含具体实现列表和大型开关-案例、映射或类似内容。它们的工作速度更快,但您必须自己编写所有对象构造逻辑。
您不必在这两个选项之间选择,您可以将它们结合起来。例如,您可以通过DI构建复杂的工厂。

1
DI容器可以被看作是一个大型的、智能的工厂方法集合,它可以使用多种方式进行配置(代码、xml、自动映射)。我称这些工厂方法为智能的,因为容器会跟踪其注册类型并将其用于创建更复杂的对象。 当使用工厂时,您需要自己设置这些依赖关系,否则您已经在使用依赖容器。

0
理想情况下,代码不应该意识到它正在使用 DI。它只是将其依赖项外部化,并假定它们已经被提供。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接