什么是解释依赖注入的好方法?

我在谷歌上找到了几个教程,但没有一个会假定读者只是Java初学者。你怎么跟一个新手解释?


我给你注射五岁儿童的依赖性。

当你从冰箱里为自己拿东西时,你可能会引起问题。你可能会把门开着,你可能会得到爸爸妈妈不想让你拥有的东西。你甚至可能在找我们没有的或者已经过期的东西。 你应该做的是陈述一个需求,“我午餐需要喝点什么,”然后我们会确保你坐下来吃饭的时候有东西。


我不知道任何简化的教程,但我可以给你一个大约250字或更少的版本:

使用依赖注入,对象不会基于它已经知道的东西来配置自己的组件,而是由更高级别的逻辑来配置对象,然后调用它没有内置预知的组件。其思想是使对象更像一个组件,而不是一个应用程序,在更高的级别上重新定位配置任务。这使得对象在未来或在不同的配置中更有可能有用。

它更适合测试,更适合修改应用程序。典型的实现是将配置放在XML中,并使用框架动态加载类。


这个呢?

如果你有一个Employee类,这个Employee类有一个Address,你可以这样定义Employee类:

class Employee {
    private Address address;

    // constructor 
    public Employee( Address newAddress ) {
        this.address = newAddress;
    }

    public Address getAddress() {
    return this.address;
    }
    public void setAddress( Address newAddress ) {
        this.address = newAddress;
    }
}

到目前为止一切看起来都很好。

这段代码显示了员工和他的地址之间的HAS-A关系,这很好。

现在,这个HAS-A关系在它们之间建立了依赖关系。问题出在构造函数内部。

每次你想创建一个Employee实例时,你都需要一个Address实例:

 Address someAddress = ....
 Employee oscar = new Employee( someAddress ); 

这种工作方式会产生问题,特别是当您想要执行单元测试时。

当您需要测试一个特定的对象时,主要的问题出现了,您需要创建另一个对象的实例,并且很可能需要创建另一个对象的实例来完成该任务。这一链条可能变得难以管理。

为了避免这种情况,你可以这样修改构造函数:

  public Employee(){
  }

使用无参数构造函数。

然后你可以随时设置地址:

 Address someAddress = ....
 Employee oscar = new Employee();
 oscar.setAddress( someAddress ); 

现在,如果您有多个属性,或者如果对象很难创建,这可能是一个拖累。

但是,考虑一下,假设您添加了Department属性:

  class Employee {
      private Address address;
      private Department department;

  ....

如果你有300个员工,他们都需要有相同的部门,而且这个部门必须在其他对象之间共享(比如公司的部门列表,或者每个部门的角色等),那么你将很难通过所有对象网络共享department对象的可见性。

依赖注入的作用是帮助你在代码中“注入”这些依赖。大多数框架允许你通过在一个外部文件中指定注入什么对象来做到这一点。

假设一个虚构的依赖注入器的属性文件:

  #mock employee
  employee.address = MockAddress.class
  employee.department = MockDepartment.class

  #production setup 
  employee.address = RealAddress.class
  employee.department = RealDepartment.class

您将定义为给定场景注入什么。

依赖注入器框架要做的是为你设置正确的对象,所以你不需要编码setAddress或setDepartment。这可以通过反射、代码生成或其他技术来完成。

因此,下次需要测试Employee类时,您可以注入模拟Address和Departments对象,而不必为所有测试编写所有的set/get代码。更棒的是,您可以在产品代码中注入真实的Address和Department对象,并且仍然确信您的代码与测试一样工作。

差不多就是这样了。

我仍然不认为这个解释适合你要求的一个5岁的孩子。

我希望你仍然觉得它有用。


当编写一个类时,它自然会使用其他对象。例如,您可能有一个数据库连接,或者您使用的其他服务。这些其他对象(或服务)是依赖关系。编写代码最简单的方法就是创建和使用这些其他对象。但这意味着您的对象与这些依赖项的关系是不灵活的:无论您为什么调用对象,它都使用相同的依赖项。

更强大的技术是能够创建对象并为其提供使用的依赖项。因此,您可以创建一个数据库连接来使用,然后将它交给您的对象。通过这种方式,您可以在不同的时间创建具有不同依赖关系的对象,从而使对象更加灵活。这就是依赖注入,将依赖“注入”到对象中。

顺便说一句:在使用flickr照片来说明概念的现代演示风格中,这可以用一个瘾君子给自己注射毒品来说明。哦,等等,那是注射依赖…好吧,不好意思,不好意思。


当你得到一台新的任天堂时,你只需要使用按钮和触摸屏就可以玩游戏。

但在任天堂的工厂,他们需要知道如何组装一个。

当工厂里的聪明人拿出一台任天堂DS时,它的内部会有所不同,但你仍然知道如何使用它。