引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
当前回答
在我看来,使用依赖注入更好,如果你是: 1. 将代码部署在小分区中,因为它可以很好地解耦一个大代码。 2. 可测试性是DI可以使用的情况之一,因为你可以很容易地模拟非去耦的对象。通过使用接口,您可以轻松地模拟和测试每个对象。 3.你可以同时修改程序的每一部分,而不需要编码它的另一部分,因为它是松散解耦的。
其他回答
我建议保持概念的简单明了。依赖注入更像是一种松散耦合软件组件的体系结构模式。工厂模式只是将创建其他类的对象的职责分离给另一个实体的一种方法。工厂模式可以被称为实现依赖注入的工具。依赖注入可以通过多种方式实现,比如使用构造函数进行依赖注入,使用映射xml文件等。
依赖注入的一个缺点是它不能用逻辑初始化对象。例如,当我需要创建一个随机名称和年龄的字符时,DI不是工厂模式的选择。使用工厂,我们可以很容易地从对象创建中封装随机算法,它支持一种称为“封装变化”的设计模式。
当使用工厂时,您的代码实际上仍然负责创建对象。通过DI,你可以将职责外包给另一个类或框架,这与你的代码是分开的。
简单来说,依赖注入和工厂方法分别意味着推和拉机制。
拉机制:类间接依赖于工厂方法,工厂方法又依赖于具体类。
推送机制:根组件可以在一个位置配置所有依赖组件,从而促进高维护和松耦合。
使用Factory方法时,创建新对象的责任仍然由类承担(尽管是间接的),而使用依赖注入时,责任是外包的(尽管是以泄露抽象为代价)。
DI为您提供了一个组合根,这是连接对象图的一个集中位置。这往往使对象依赖关系非常显式,因为对象确切地要求它们所需要的东西,并且只有一个地方可以得到它。
组合根是一种清晰而直接的关注点分离。被注入的对象应该不依赖于DI机制,无论是第三方容器还是DIY DI。DI应该是不可见的。
工厂往往更加分散。不同的对象使用不同的工厂,工厂表示对象与其实际依赖关系之间的额外间接层。这个附加层将自己的依赖项添加到对象图中。工厂不是看不见的。工厂是一个中间商。
因此,更新工厂的问题更大:因为工厂是业务逻辑的依赖项,修改它们可能会产生连锁反应。组合根不是业务逻辑的依赖项,因此可以单独修改它。
GoF提到了更新抽象工厂的困难。他们的部分解释被引用在这里的回答中。将DI与工厂进行对比也与ServiceLocator是否是反模式这个问题有很多相似之处。
最终,选择哪个答案可能是固执己见的;但我认为这可以归结为一个工厂是一个中间人。问题在于,除了提供产品之外,这个中间商是否还能通过增加额外价值来发挥自己的作用。因为如果你能在没有中间商的情况下得到同样的产品,那为什么不把中间商去掉呢?
一个图表有助于说明其中的区别。