依赖注入原理
本文转自:http://codethink.me/2015/08/01/dependency-injection-theory/0. 前言在软件工程领域,依赖注入(Dependency Injection)是用于实现控制反转(Inversion of Control)的最常见的方式之一。本文主要介绍依赖注入原理和常见的实现方式,重点在于介绍这种年轻的设计模式的适用场景及优势。1. 为什么需要依赖注入控制反转用于解耦,解的究竟是谁和谁的耦?这是我在最初了解依赖注入时候产生的第一个问题。下面我引用Martin Flower在解释介绍注入时使用的一部分代码来说明这个问题。public class MovieLister {
private MovieFinder finder;
public MovieLister() {
finder = new MovieFinderImpl();
}
public Movie[] moviesDirectedBy(String arg) {
List allMovies = finder.findAll();
for (Iterator it = allMovies.iterator(); it.hasNext();) {
Movie movie = (Movie) it.next();
if (!movie.getDirector().equals(arg)) it.remove();
}
return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
}
...
}
public interface MovieFinder {
List findAll();
}
我们创建了一个名为MovieLister的类来提供需要的电影列表,它moviesDirectedBy方法提供根据导演名来搜索电影的方式。真正负责搜索电影的是实现了MovieFinder接口的MovieFinderImpl,我们的MovieLister类在构造函数中创建了一个MovieFinderImpl的对象。 2. 依赖注入的实现方式2.1 构造函数注入(Contructor Injection)这是我认为的最简单的依赖注入方式,我们修改一下上面代码中MovieList的构造函数,使得MovieFinderImpl的实现在MovieLister类之外创建。这样,MovieLister就只依赖于我们定义的MovieFinder接口,而不依赖于MovieFinder的实现了。 public class MovieLister {
private MovieFinder finder;
public MovieLister(MovieFinder finder) {
this.finder = finder;
}
...
}
2.2 setter注入类似的,我们可以增加一个setter函数来传入创建好的MovieFinder对象,这样同样可以避免在MovieFinder中hard init这个对象。 public class MovieLister {
s...
public void setFinder(MovieFinder finder) {
this.finder = finder;
}
}
2.3 接口注入接口注入使用接口来提供setter方法,其实现方式如下。首先要创建一个注入使用的接口。 public interface InjectFinder {
void injectFinder(MovieFinder finder);
}
class MovieLister implements InjectFinder {
...
public void injectFinder(MovieFinder finder) {
this.finder = finder;
}
...
}
3. 最后依赖注入降低了依赖和被依赖类型间的耦合,在修改被依赖的类型实现时,不需要修改依赖类型的实现,同时,对于依赖类型的测试,可以更方便的使用mocking object替代原有的被依赖类型,以达到对依赖对象独立进行单元测试的目的。最后需要注意的是,依赖注入只是控制反转的一种实现方式。控制反转还有一种常见的实现方式称为依赖查找。参考
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |