什么是依赖注入?

已经发布了几个关于依赖注入的具体问题的问题,比如何时使用它以及它有哪些框架。 然而,

什么是依赖注入以及何时/为什么应该或不应该使用它?


基本上,不是让对象创建一个依赖关系或要求工厂对象为其创建一个对象,而是将所需的依赖关系传递给外部对象,并使其成为别人的问题。 这个“某人”或者是依赖关系图上的对象,或者是构建依赖关系图的依赖注入器(框架)。 我在这里使用的依赖关系是当前对象需要引用的任何其他对象。

依赖注入的一个主要优点是它可以使测试更容易。 假设你有一个在其构造函数中做了如下操作的对象:

public SomeClass() {
    myObject = Factory.getObject();
}

当你想要做的是在SomeClass上运行一些单元测试时,这可能很麻烦,特别是如果myObject是复杂的磁盘或网络访问。 所以现在你正在嘲笑myObject,但也以某种方式拦截工厂调用。 硬。 相反,将该对象作为参数传递给构造函数。 现在,您已将问题转移到其他地方,但测试可能变得更容易。 只需制作一个虚拟的myObject并将其传入即可。构造函数现在看起来有点像:

public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

这是依赖注入的一种风格 - 通过构造函数。 有几种机制是可能的。

  • 正如在评论中指出的那样,一种常见的选择是定义一个无所作为的构造函数,并通过属性设置器(h / t @MikeVella)注入依赖项。
  • Martin Fowler记录了第三种替代方法(h / t @MarcDix),其中类明确实现了他们希望注入的依赖关系的接口。
  • 当不使用依赖注入时(例如在构造函数中做了太多工作的类中),在单元测试中分离组件变得越来越困难。

    回到2013年,当我写这个答案时,这是Google测试博客上的一个主题。 这对我来说仍然是最大的优势,因为您可能并不总是需要运行时设计中的额外灵活性(例如,对于服务定位器或类似模式),但您经常需要在测试期间隔离您的类。


    到目前为止,我发现的最好的定义是詹姆斯肖尔的一个定义:

    “依赖注入”是一个5美分概念的25美元术语。 [...]依赖注入意味着给对象实例变量。 [...]。

    Martin Fowler的一篇文章可能也有用。

    依赖注入基本上提供了一个对象需要的对象(它的依赖),而不是让它自己构造它们。 这是一种非常有用的测试技术,因为它允许依赖性被嘲弄或被剔除。

    通过许多方法(例如构造函数注入或setter注入)可以将依赖关系注入到对象中。 人们甚至可以使用专门的依赖注入框架(例如Spring)来做到这一点,但它们当然不是必需的。 你不需要这些框架来进行依赖注入。 显式实例化和传递对象(依赖关系)与框架注入一样好。


    我发现这个有趣的例子是松耦合:

    任何应用程序都由许多对象组成,它们彼此协作以执行一些有用的事情。 传统上,每个对象都负责获取自己对其协作的依赖对象(依赖关系)的引用。 这导致高度耦合的类和难以测试的代码。

    例如,考虑一个Car对象。

    Car取决于车轮,发动机,燃料,电池等运行。 传统上,我们定义了这些依赖对象的品牌以及Car对象的定义。

    无依赖注入(DI):

    class Car{
      private Wheel wh= new NepaliRubberWheel();
      private Battery bt= new ExcideBattery();
    
      //The rest
    }
    

    在这里, Car对象负责创建依赖对象。

    如果我们想在初始的NepaliRubberWheel()刺破之后改变它的依赖对象的类型 - 比如说Wheel ? 我们需要用它的新依赖关系重新创建Car对象,如ChineseRubberWheel() ,但只有Car制造商可以做到这一点。

    那么Dependency Injection对我们有什么作用?

    当使用依赖注入时,对象在运行时被赋予它们的依赖关系,而不是编译时间(汽车制造时间)。 所以我们现在可以随时改变Wheel 。 在这里, dependencywheel )可以在运行时注入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;
      }
    }
    

    来源:了解依赖注入

    链接地址: http://www.djcxy.com/p/251.html

    上一篇: What is dependency injection?

    下一篇: What is tail recursion?