已经发布了几个关于依赖注入的具体问题的问题,例如何时使用它以及它有哪些框架。然而,
什么是依赖注入以及何时 / 为什么应该或不应该使用它?
到目前为止,我发现的最佳定义是James Shore :
对于 5 美分的概念,“依赖注入” 是一个 25 美元的术语。 [...] 依赖注入意味着为对象提供其实例变量。 [...]。
Martin Fowler 的一篇文章也可能证明是有用的。
依赖注入基本上是提供对象所需的对象(它的依赖关系),而不是让它自己构造它们。它是一种非常有用的测试技术,因为它允许模拟或删除依赖项。
可以通过多种方式(例如构造函数注入或 setter 注入)将依赖项注入到对象中。甚至可以使用专门的依赖注入框架(例如 Spring)来做到这一点,但它们当然不是必需的。您不需要这些框架具有依赖注入。显式地实例化和传递对象(依赖关系)与框架注入一样好。
基本上,不是让对象创建依赖项或要求工厂对象为它们创建一个依赖项,而是将所需的依赖项传递给外部对象,并使其成为别人的问题。这个 “某人” 要么是依赖图之上的对象,要么是构建依赖图的依赖注入器(框架)。我在这里使用它的依赖是当前对象需要持有引用的任何其他对象。
依赖注入的一个主要优点是它可以使测试更容易。假设您有一个对象,在其构造函数中执行以下操作:
public SomeClass() {
myObject = Factory.getObject();
}
当你想要做的只是在 SomeClass 上运行一些单元测试时,这可能很麻烦,特别是如果 myObject 是复杂磁盘或网络访问的话。所以现在你正在考虑模仿 myObject,但也以某种方式拦截工厂调用。硬。相反,将对象作为参数传递给构造函数。现在你已将问题转移到其他地方,但测试可以变得更容易。只需创建一个虚拟 myObject 并将其传入。构造函数现在看起来有点像:
public SomeClass (MyClass myObject) {
this.myObject = myObject;
}
这是一种依赖注入方式 - 通过构造函数。有几种机制是可能的。
当不使用依赖注入时(例如在其构造函数中执行过多工作的类等),在单元测试中隔离组件往往变得更加困难。
早在 2013 年,当我写这个答案时,这是Google 测试博客的一个主题。这对我来说仍然是最大的优势,因为您可能并不总是需要在运行时设计中具有额外的灵活性(例如,对于服务定位器或类似的模式),但是您通常需要能够在测试期间隔离您的类。
我发现松耦合这个有趣的例子:
任何应用程序都由许多对象组成,这些对象彼此协作以执行一些有用的东西。传统上,每个对象都负责获取它自己对与之协作的依赖对象(依赖项)的引用。这导致高度耦合的类和难以测试的代码。
例如,考虑一个Car
对象。
Car
取决于车轮,发动机,燃料,电池等运行。传统上,我们定义此类依赖对象的品牌以及Car
对象的定义。
没有依赖注入(DI):
class Car{
private Wheel wh = new NepaliRubberWheel();
private Battery bt = new ExcideBattery();
//The rest
}
这里, Car
对象负责创建依赖对象。
如果我们想在最初的NepaliRubberWheel()
穿孔后更改其依赖对象的类型(比如Wheel
NepaliRubberWheel()
会怎么样?我们需要重新创建具有新依赖关系的 Car 对象,例如ChineseRubberWheel()
,但只有Car
制造商才能这样做。
那么Dependency Injection
为我们做了什么......?
使用依赖项注入时,会在运行时向对象提供其依赖项,而不是编译时间(汽车制造时间) 。这样我们现在可以随时更换Wheel
。这里, dependency
( wheel
)可以在运行时注入Car
。
使用依赖注入后:
在这里,我们在运行时注入 依赖项 (Wheel 和 Battery)。因此术语: 依赖注入。
class Car{
private Wheel wh = [Inject an Instance of Wheel (dependency of car) at runtime]
private Battery bt = [Inject an Instance of Battery (dependency of car) at runtime]
Car(Wheel wh,Battery bt) {
this.wh = wh;
this.bt = bt;
}
//Or we can have setters
void setWheel(Wheel wh) {
this.wh = wh;
}
}
来源: 了解依赖注入