引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
当前回答
我使用这两种方法来创建反转控制策略,为在我之后需要维护它的开发人员提供了更强的可读性。
我使用工厂来创建不同的层对象(业务,数据访问)。
ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness();
另一个开发人员会看到这一点,当创建业务层对象时,他会在BusinessFactory中查看,智能感知会为开发人员提供所有可能创建的业务层。不需要玩游戏,找到我想要创建的界面。
这个结构已经是控制反转了。我不再负责创建特定的对象。但是您仍然需要确保依赖注入能够轻松地更改内容。 创建自己的自定义依赖注入是荒谬的,所以我使用Unity。在CreateCarBusiness()中,我要求Unity解决哪个类属于这个和它的生命周期。
所以我的代码工厂依赖注入结构是:
public static class BusinessFactory
{
public static ICarBusiness CreateCarBusiness()
{
return Container.Resolve<ICarBusiness>();
}
}
现在我两者兼得。我的代码对于其他开发人员来说也更易于阅读,因为我使用的对象的范围,而不是构造函数依赖注入,它只是说在创建类时每个对象都是可用的。
当我创建单元测试时,我使用它将我的数据库数据访问更改为自定义编码的数据访问层。我不希望我的单元测试与数据库、网络服务器、电子邮件服务器等通信。他们需要测试我的业务层,因为这是智能所在。
其他回答
比诺,
我不认为你必须选择其中一个而不是另一个。
将依赖类或接口移动到类构造函数或setter的行为遵循DI模式。传递给构造函数或集合的对象可以用Factory实现。
什么时候使用?使用开发人员擅长的模式。他们觉得什么最舒服,什么最容易理解。
简单来说,依赖注入和工厂方法分别意味着推和拉机制。
拉机制:类间接依赖于工厂方法,工厂方法又依赖于具体类。
推送机制:根组件可以在一个位置配置所有依赖组件,从而促进高维护和松耦合。
使用Factory方法时,创建新对象的责任仍然由类承担(尽管是间接的),而使用依赖注入时,责任是外包的(尽管是以泄露抽象为代价)。
依赖注入(DI)和工厂模式相似的原因是它们是控制反转(IoC)的两种实现,IoC是一种软件架构。简单地说,它们是同一问题的两种解决方案。
因此,为了回答这个问题,工厂模式和依赖注入模式之间的主要区别在于如何获得对象引用。依赖项注入顾名思义就是将引用注入或提供给您的代码。使用工厂模式,您的代码必须请求引用,以便您的代码获取对象。这两种实现都删除或解耦了代码与所使用的对象引用的底层类或类型之间的链接。
值得注意的是,工厂模式(或者实际上是抽象工厂模式,即返回返回对象引用的新工厂的工厂)可以被编写为在运行时动态地选择或链接到被请求的对象类型或类。这使得它们与服务定位器模式非常相似(甚至比DI更相似),后者是IoC的另一个实现。
工厂设计模式相当古老(就软件而言),并且已经存在了一段时间。由于IoC体系结构模式最近的流行,它正在复苏。
我想当涉及到IoC设计模式时:注入器被注入,定位器被定位,工厂被重构。
我相信DI是一种配置或即时化bean的方法。DI可以通过很多方式来实现,比如构造函数,setter-getter等等。
工厂模式只是实例化bean的另一种方式。此模式将主要用于必须使用工厂设计模式创建对象时,因为在使用此模式时,您不配置bean的属性,只实例化对象。
检查这个链接:依赖注入
我认为它们是正交的,可以一起使用。让我给你看一个我最近在工作中遇到的例子:
我们使用Java中的Spring框架进行DI。一个单例类(Parent)必须实例化另一个类(Child)的新对象,这些对象有复杂的协作者:
@Component
class Parent {
// ...
@Autowired
Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
this.dep1 = dep1;
this.dep2 = dep2;
}
void method(int p) {
Child c = new Child(dep1, dep2, ..., depN, p);
// ...
}
}
在这个例子中,Parent必须接收DepX实例,并将它们传递给Child构造函数。问题在于:
Parent对Child的了解比它应该了解的要多 母公司的合作者太多了 向Child添加依赖项需要更改Parent
这时我意识到工厂非常适合这里:
它隐藏了Child类的所有真实参数,就像Parent所看到的那样 它封装了创建子节点的知识,这些知识可以集中在DI配置中。
这是简化的Parent类和ChildFactory类:
@Component
class Parent {
// ...
@Autowired
Parent(ChildFactory childFactory) {
this.childFactory = childFactory;
}
void method(int p) {
Child c = childFactory.newChild(p);
// ...
}
}
@Component
class ChildFactory {
// ...
@Autowired
Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
this.dep1 = dep1;
this.dep2 = dep2;
// ...
this.depN = depN;
}
Child newChild(int p) {
return new Child(dep1, dep2, ..., depN, p);
}
}