- 1、本文档共7页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
深度理解依赖注入
深度理解依赖注入(Dependence Injection)
前面的话:提到依赖注入,大家都会想到老马那篇经典的文章。其实,本文就是相当于对那篇文章的解读。所以,如果您对原文已经有了非常深刻的理解,完全不需要再看此文;但是,如果您和笔者一样,以前曾经看过,似乎看懂了,但似乎又没抓到什么要领,不妨看看笔者这个解读,也许对您理解原文有一定帮助。1.依赖在哪里?? 老马举了一个小例子,是开发一个电影列举器(MovieList),这个电影列举器需要使用一个电影查找器(MovieFinder)提供的服务,伪码如下:
?1/**//*服务的接口*/?2public?interface?MovieFinder?{?3????ArrayList?findAll();?4}?5?6/**//*服务的消费者*/?7class?MovieLister?8{?9????public?Movie[]?moviesDirectedBy(String?arg)?{10????????List?allMovies?=?finder.findAll();11????????for?(Iterator?it?=?allMovies.iterator();?it.hasNext();)?{12????????????Movie?movie?=?(Movie)?it.next();13????????????if?(!movie.getDirector().equals(arg))?it.remove();14????????}15????????return?(Movie[])?allMovies.toArray(new?Movie[allMovies.size()]);16????}1718????/**//*消费者内部包含一个将指向具体服务类型的实体对象*/19????private?MovieFinder?finder;20????/**//*消费者需要在某一个时刻去实例化具体的服务。这是我们要解耦的关键所在,21?????*因为这样的处理方式造成了服务消费者和服务提供者的强耦合关系(这种耦合是在编译期就确定下来的)。22?????**/23????public?MovieLister()?{24????????finder?=?new?ColonDelimitedMovieFinder(movies1.txt);25????}26}
从上面代码的注释中可以看到,MovieLister和ColonDelimitedMovieFinder(这可以使任意一个实现了MovieFinder接口的类型)之间存在强耦合关系,如下图所示:图1这使得MovieList很难作为一个成熟的组件去发布,因为在不同的应用环境中(包括同一套软件系统被不同用户使用的时候),它所要依赖的电影查找器可能是千差万别的。所以,为了能实现真正的基于组件的开发,必须有一种机制能同时满足下面两个要求:?(1)解除MovieList对具体MoveFinder类型的强依赖(编译期依赖)。?(2)在运行的时候为MovieList提供正确的MovieFinder类型的实例。?? 换句话说,就是在运行的时候才产生MovieList和MovieFinder之间的依赖关系(把这种依赖关系在一个合适的时候“注入”运行时),这恐怕就是Dependency Injection这个术语的由来。再换句话说,我们提到过解除强依赖,这并不是说MovieList和MovieFinder之间的依赖关系不存在了,事实上MovieList无论如何也需要某类MovieFinder提供的服务,我们只是把这种依赖的建立时间推后了,从编译器推迟到运行时了。?? 依赖关系在OO程序中是广泛存在的,只要A类型中用到了B类型实例,A就依赖于B。前面笔者谈到的内容是把概念抽象到了服务使用者和服务提供者的角度,这也符合现在SOA的设计思路。从另一种抽象方式上来看,可以把MovieList看成我们要构建的主系统,而MovieFinder是系统中的plugin,主系统并不强依赖于任何一个插件,但一旦插件被加载,主系统就应该可以准确调用适当插件的功能。?? 其实不管是面向服务的编程模式,还是基于插件的框架式编程,为了实现松耦合(服务调用者和提供者之间的or框架和插件之间的),都需要在必要的位置实现面向接口编程,在此基础之上,还应该有一种方便的机制实现具体类型之间的运行时绑定,这就是DI所要解决的问题。2.DI的实现方式?? 和上面的图1对应的是,如果我们的系统实现了依赖注入,组件间的依赖关系就变成了图2:图2说白了,就是要提供一个容器,由容器来完成(1)具体ServicePr
文档评论(0)