引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
当前回答
依赖注入的一个缺点是它不能用逻辑初始化对象。例如,当我需要创建一个随机名称和年龄的字符时,DI不是工厂模式的选择。使用工厂,我们可以很容易地从对象创建中封装随机算法,它支持一种称为“封装变化”的设计模式。
其他回答
[Factory] ->有一个基于请求参数创建类的类。毕竟,“工厂”在现实世界中也为你制造“物品”。你可以让你的汽车供应商工厂生产(免费:)特斯拉。1给你。
[DI] ->一个(服务)容器,用于存储接口(压缩类)。你不关心创建对象。你只需要让某个人/某个地方实现它,细节和其他东西对你、调用者或消费者都不重要。
DI是SOLID原则中“D”的基础。
Life cycle management is one of the responsibilities dependency containers assume in addition to instantiation and injection. The fact that the container sometimes keep a reference to the components after instantiation is the reason it is called a "container", and not a factory. Dependency injection containers usually only keep a reference to objects it needs to manage life cycles for, or that are reused for future injections, like singletons or flyweights. When configured to create new instances of some components for each call to the container, the container usually just forgets about the created object.
来自:http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
当我读到关于DI的文章时,我也有同样的问题。 最后,这就是我所理解的,但如果我错了,请纠正我。
“很久以前,有一些小国,它们有自己的管理机构,根据自己的成文规则进行控制和决策。后来形成了一个大政府,消除了所有这些小的管理机构,这些机构只有一套规则(宪法),并通过法院执行。”
小王国的管理机构是“工厂”
大政府是“依赖注入器”。
这里的大多数答案都解释了两者的概念差异和实现细节。但是我无法解释在应用上的差异,IMO是最重要的,OP问的是什么。所以让我重新讨论这个话题……
曾经有人告诉我,你如何使用它才会有所不同!
完全正确。在90%的情况下,你可以使用Factory或DI来获取对象引用,通常你最终会使用后者。在另外10%的情况下,使用Factory是唯一正确的方法。这些情况包括通过运行时参数的变量获取对象。是这样的:
IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com",
useCookies: false, connectionTimeout: 120);
在这种情况下,从DI获取客户端是不可能的(或者至少需要一些丑陋的解决方案)。因此,作为决策的一般规则:如果可以在没有任何运行时计算参数的情况下获得依赖项,则首选DI,否则使用Factory。
DI为您提供了一个组合根,这是连接对象图的一个集中位置。这往往使对象依赖关系非常显式,因为对象确切地要求它们所需要的东西,并且只有一个地方可以得到它。
组合根是一种清晰而直接的关注点分离。被注入的对象应该不依赖于DI机制,无论是第三方容器还是DIY DI。DI应该是不可见的。
工厂往往更加分散。不同的对象使用不同的工厂,工厂表示对象与其实际依赖关系之间的额外间接层。这个附加层将自己的依赖项添加到对象图中。工厂不是看不见的。工厂是一个中间商。
因此,更新工厂的问题更大:因为工厂是业务逻辑的依赖项,修改它们可能会产生连锁反应。组合根不是业务逻辑的依赖项,因此可以单独修改它。
GoF提到了更新抽象工厂的困难。他们的部分解释被引用在这里的回答中。将DI与工厂进行对比也与ServiceLocator是否是反模式这个问题有很多相似之处。
最终,选择哪个答案可能是固执己见的;但我认为这可以归结为一个工厂是一个中间人。问题在于,除了提供产品之外,这个中间商是否还能通过增加额外价值来发挥自己的作用。因为如果你能在没有中间商的情况下得到同样的产品,那为什么不把中间商去掉呢?
一个图表有助于说明其中的区别。