DI 容器与工厂

DI-container vs. Factories

我知道有很多关于依赖注入的文章和线程,但没有那么多关于依赖注入容器的文章。我发现 this one by Fabien Potencier 非常有用,尽管它针对的是 PHP。然而,我对这些容器了解得越多,我得出的结论是 none 不仅仅是工厂方法的简单集合,这是真的吗?

更深入更具体的观点: 向对象注入依赖项时

foo.Bar = new Dependency();

我也会写

foo.Bar = new myFactory.CreateDependency();

或使用容器

foo.Bar = myContainer.CreateDependency();

这里最后一个方法中的容器不仅有一个而且还有许多其他方法来创建其他类型,所以它只是一个工厂方法的容器,对吧?

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

DI 容器的全部意义在于你永远不会 need/should 编写像

这样的代码
foo.Bar = myContainer.CreateDependency();

它被认为是一种反模式。 DI容器只能在Composition Root中使用一次(这是一个主要的DI容器使用模式)。

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

终身管理。因此,每次需要依赖时,容器都可能注入相同的对象(单例生命周期),或者 return 每次都是新的。

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

你可以看看这本书Dependency Injection in .NET。它对我理解 DI 容器、使用模式和一般的依赖注入有很大帮助。

理想情况下,代码应该不知道它是 运行 DI。 它只是将其依赖项外部化并假定已提供它们。

您可以将 DI-container/library 视为具有许多高级对象构造方法(通过反射)的工厂框架。它很有用,因为通常您不必编写任何高级方法,例如,用于加载插件程序集和获取插件数据类型。但缺点是反射很慢,在你的应用程序初始化阶段使用它是合理的。但是,如果你想在运行时用它创建很多小对象,它会减慢你的速度。

另一方面,您自己的工厂是定制的,通常包含具体实现的列表和大的开关盒,或地图或类似的东西。它们工作得更快,但您必须自己编写所有对象构造逻辑。

您不必在这两个选项之间做出选择,您可以将它们结合起来。比如可以通过DI

构造复杂工厂