关于本文

Dependency injection,依赖注入,这是我在学习 Angular 的过程中,遇到的一个坎。刚看到「依赖注入」几个字时,完全不知所云,花了些时间,算是有所理解。本文算是记录下我目前的理解,希望对和我一样初次接触到依赖注入的同学有所帮助。

Angular 的文档中,关于依赖注入的具体使用,写的很清楚。本文的重点是:为什么需要依赖注入。在说清楚「为什么」以后,依赖注入「是什么」也就清晰了。

Why?

问题的起点

看下面这段代码:

这段代码有什么问题?就这么看其实没问题,直到出现一些变化。

变化1

现在有一个新要求,ClassA 的构造函数接受一个参数,给 word 属性赋值,让 A 可以讲更多的话而不仅仅是一句 “Hello”。要给 A 一个参数很容易:

但问题是,A 的实例化在 B 的构造函数中进行,我们势必要去 B 中修改,给 A 传递一个参数。

  1. 这会带来麻烦:如果 A 同时还在其他构造函数中被实例化,那就得一个个的改;
  2. 这不合理:A 需要作出改变,我们不只改了 A,还得改 B,B 并没有发生需求上的变化。

变化2

现在增加了 C:

我想增加一个像 B 一样的模块来调用 C,也许它叫 D:

显然,B 和 D 功能完全重复了,但又不得不写成两个不同的模块,因为它们的依赖不同。

解决方案

A 和 C 保持原状:

B 进行改写:

此时,D 已经完全不需要了,解决了 B 重用的问题。如果 A 需要接受一个参数,那么改写 A:

现在 A 的需求更改,已经和 B 没有关系了,B 不用做出任何改变。

小结

简单的说,我们面临的问题,是模块之间强烈的依赖关系带来的。打断这种依赖关系的方法,就是将依赖从外部传入,以取代在内部生成依赖的方式。这种将依赖从外部传入构造函数的方式,即依赖注入。

依赖注入的其他优势

单元测试

解释依赖注入,MVC 结构的代码是个好例子:

如果我们想测试 Controller,由于依赖于 Model,而 Model 又用 Ajax 从后台取了数据,所以这个测试一定要在工作环境下才能进行。

如果用依赖注入方式改写 Controller:

我们就可以创造一个假的 model 测试 Controller:

Tagged:

发表评论

电子邮件地址不会被公开。 必填项已用*标注