引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
当前回答
工厂设计模式
工厂设计模式的特点是
一个接口 实现类 一个工厂
当你这样问自己时,你可以观察到一些事情
工厂什么时候为实现类创建对象——运行时还是编译时? 如果您想在运行时切换实现,该怎么办?-不可能
这些是由依赖注入处理的。
依赖注入
您可以使用不同的方式注入依赖项。为了简单起见,让我们使用接口注入
在DI中,容器创建所需的实例,并将它们“注入”到对象中。
这样就消除了静态实例化。
例子:
public class MyClass{
MyInterface find= null;
//Constructor- During the object instantiation
public MyClass(MyInterface myInterface ) {
find = myInterface ;
}
public void myMethod(){
find.doSomething();
}
}
其他回答
IOC is a concept which is implemented by two ways. Dependency creation and dependency injection, Factory/Abstract factory are the example of dependency creation. Dependency injection is constructor, setter and interface. The core of IOC is to not depend upon the concrete classes, but define the abstract of methods(say an Interface/abstract class) and use that abstract to call method of concrete class. Like Factory pattern return the base class or interface. Similariliy dependency injection use base class/interface to set value for objects.
我建议保持概念的简单明了。依赖注入更像是一种松散耦合软件组件的体系结构模式。工厂模式只是将创建其他类的对象的职责分离给另一个实体的一种方法。工厂模式可以被称为实现依赖注入的工具。依赖注入可以通过多种方式实现,比如使用构造函数进行依赖注入,使用映射xml文件等。
您可以在这个链接中查看两种(和其他)方法在实际示例中的比较。
基本上,当需求发生变化时,如果您使用工厂而不是DI,您最终会修改更多的代码。
这对于手动DI也是有效的(例如,当没有外部框架为你的对象提供依赖关系,但你在每个构造函数中传递它们时)。
我认为它们是正交的,可以一起使用。让我给你看一个我最近在工作中遇到的例子:
我们使用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);
}
}
依赖注入的一个缺点是它不能用逻辑初始化对象。例如,当我需要创建一个随机名称和年龄的字符时,DI不是工厂模式的选择。使用工厂,我们可以很容易地从对象创建中封装随机算法,它支持一种称为“封装变化”的设计模式。