简述控制反转ioc_控制反转(IoC) 的理解

控制反转是一个常见的面向对象技术,它主要应用在框架中。如 GUI框架,Spring框架等,这些框架为设计特定的应用程序提供了一般性的步骤,框架把核心的控制流程集成于自身,仅仅把一些具体的实现任务交给用户(程序员即为框架的用户),正是由于这些框架的产生才有必要用到控制反转技术。 也就是说,如果GUI框架仅仅被一个人使用,那么完全不用控制反转也行,因为此框架仅为一个人使用,这个人使用的类是什么样子的,有什么样的类,这个人心里很明白,它可以把这些类写死在代码中。 但这个框架如果被许多人使用,就需要考虑控制反转问题了。看例子:

下面例子的作用是:提供一个导演的名子给 moviesDirectedBy 方法,它就能返回此导演所导演过的所有电影。

class MovieLister...

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()]);

}

现在的问题是  finder 是个什么东西,它是如何实现的?如下代码所示:

public interface MovieFinder {

List findAll();

}

class MovieLister...

private MovieFinder finder;

public MovieLister() {

finder = new ColonDelimitedMovieFinder("movies1.txt");

}

finder 可以看成是一个接口即MovieFinder,在 MovieLister类的构造函数中对它进行了实例化,即

finder = new ColonDelimitedMovieFinder("movies1.txt");

ColonDelimitedMovieFinder类从一个以冒号分隔的 文本文件中读取电影列表。

从现在来看,上面的实现都算顺利,没有发现不托之处,现在问题来了:

我的一个朋友想使用我的代码,即想使用我的 MovieLister 类, 我的MovieLister类现在有了"框架"的味道了。但朋友的 MovieFinder如何实现我可不确定,它也许把电影列表存储在XML文件中或者直接从网上请求的,那么MovieLister如何去实例化 MovieFinder呢,没有办法直接实现。现在类的关系如下图:

0818b9ca8b590ca3270a3433284dd417.png

MovieLister需要实例化一个 MovieFinderImpl 来找出所有的电影列表,而现在这个 MovieFindImpl 是个什么样子的根本不确定,那么这个问题如何解决。

解决办法如下图所示:

0818b9ca8b590ca3270a3433284dd417.png

引入一个 Assembler 的装配类,由这个类来告诉 MovieLister  MovieFinderImpl具体是什么,这个装配过程在运行时通过Java反射机制来完成,这个装配的过程也就是Dependency Injection(依赖注入), 依赖注入有三种方式,分别为:

1 通过构造函数依赖注入

2 通过配置文件依赖注入

3 通过接口依赖注入

在这里只讨论第2种情况:通过配置文件依赖注入(这也是Spring 框架常用的方式)

class MovieLister...

private MovieFinder finder;

public void setFinder(MovieFinder finder) {

this.finder = finder;

}

class ColonMovieFinder...

public void setFilename(String filename) {

this.filename = filename;

}

movies1.txt

public void testWithSpring() throws Exception {

ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");

MovieLister lister = (MovieLister) ctx.getBean("MovieLister");

Movie[] movies = lister.moviesDirectedBy("Sergio Leone");

assertEquals("Once Upon a Time in the West", movies[0].getTitle());

}

配置文件就是指 上上图的 XML文件,在配置文件中声明了 MovieLister,同时也定义了 MovieLister 所关联的 MovieFinder;配置文件中也声明了 MovieFinder,这个MovieFinder 标签指明了一个 MovieFinderImpl即 ColonMovieFinder,整个 MovieLister框在运行时会动态的加载 XML 文件,并从中提取出 MovieLister和MovieFinder 的相关信息,并用反射机制实例化了具体的 MovieFinderImpl。

在这里有个重点:

MovieLister类的编写必须按照一定的格式,框架才能为其“注入”适当的类,这个格式就是:

class MovieLister...

private MovieFinder finder;

public void setFinder(MovieFinder finder) {

this.finder = finder;

}

即类的编写必须写一个 private MovieFinder finder  并写一个 setFinder 的方法(名子必须是这样)。

其它方面的思考:

本文研究的初衷不是针对 Spring,而是针对 Android, Android的UI设计主要采用 XML 的方式,其实这也是“依赖注入”的形式。可以想一想程序中的每一个 Activity,Service等组件都是要在 manifest.xml中声明的,不然程序就会出错。也就是Android框架把你 XML 文件中的 Activity等注入到 Android的 framework 中,这样系统就能正常运行起来了。注入 Android 框架中的 Activity 必须从 android.app.Activity 继承,而且还要实现 onCreate/onResume/onPause 等方法,这就相当于 MovieFinder 的具体类必须实现 MovieFinder接口一样,这是框架内部需要调用的方法。

关于 Android总结为一句话帮助自己记忆:

manifest.xml配置了Activity,框架读取xml并把注册的Activity注入到框架中,并调用规定好的 Activity 的生命周期方法进行动作。

本文参考:http://www.martinfowler.com/articles/injection.html   有关“依赖注入”的介绍,需要更多了解可以点击此链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值