如何解释5岁的依赖注射?

时间:2009-10-28 17:48:10

标签: design-patterns dependency-injection inversion-of-control

解释dependency injection的好方法是什么?

我在Google上找到了几个教程,但没有一个能让读者认为只是Java初学者的教程。你会如何向新手解释这个?

5 个答案:

答案 0 :(得分:790)

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

当你自己从冰箱里拿出东西时,你可能会引发问题。你可能会把门打开,你可能得到妈咪或爸爸不希望你拥有的东西。您甚至可能正在寻找我们甚至没有或已经过期的东西。

你应该做的是说明需要,“我需要在午餐时喝点东西”,然后当你坐下来吃饭时我们会确保你有东西。

答案 1 :(得分:93)

这个怎么样?

如果您有一个班级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(){
  }

使用no args构造函数。

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

 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

您将定义为给定方案注入的内容。

Dependency Injector框架将为您设置正确的对象,因此您不必编写代码setAddresssetDepartment。这可以通过反射或通过代码生成或其他技术来完成。

因此,下次需要测试Employee类时,您可以注入模拟AddressDepartments对象,而无需为所有测试编写所有set / get代码。更好的是,您可以在生产代码中注入真正的 AddressDepartment对象,并且仍然可以确保代码在测试时正常工作。

这几乎就是它。

我仍然认为这种解释不适合您要求的5岁。

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

答案 2 :(得分:24)

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

更强大的技术是能够创建对象并为其提供依赖性。因此,您可以创建要使用的数据库连接,然后将其交给您的对象。这样,您可以在不同时间创建具有不同依赖关系的对象,从而使您的对象更加灵活。这是依赖注入,您可以将依赖项“注入”对象。

BTW:在使用flickr照片来说明概念的现代演示风格中,这可以通过吸毒者用药物射击自己来说明。哦,等等,这是注射依赖...好吧,对不起,糟糕的笑话。

答案 3 :(得分:10)

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

通过依赖注入,对象不会根据已知的内容配置自己的组件,而是由更高级别的逻辑配置对象,然后调用它没有内置预知的组件。我们的想法是使对象更多地成为组件而不是应用程序,从而将配置任务重新定位到更高级别。这使得该对象在将来或使用不同的配置时更有用。

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

答案 4 :(得分:7)

当你获得一个新的任天堂时,你可以使用按钮和触摸屏来玩游戏。

但是在任天堂工厂,他们需要知道如何把它们放在一起。

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