面向对象中的依赖注入概念本质上是否与面向过




或者换个比较实际点的例子来说,使用spring进行应用层面的依赖注入(repository注入service,service注入controller)与c中include一个模块的头文件是否在本质上是一致的。如果一致的,那么能不能这么说,从应用层面上来看,spring的依赖注入实际就是面向过程的,因为所有层上的接口都是不具备状态的?





A的构造函数接受接口IB,你注入的时候把B给了A,A这个类就成为了callback。这跟模块导入是不一样的。在做IoC的时候,千万不要把类写成主动的,他是被动的。倘若你A自己去取了B,这就化神奇为腐朽了。


这跟接口是否具备状态无关,这也不是什么面向过程,也无法跟模块导入类比。他们都是不一样的。



泻药,两者不同。

依赖注入(Dependency Injection,简称DI)体现着控制反转(Inversion of Control, 简称IoC)范式,其与你谈的#include具有着本质区别,#include以后,其主动权依然在你的手中,只是#include的东西为你提供了你可以call的东西,然而DI却不是,而是让你很舒服的使用,控制权不在你的手中。举一个简单通俗的说法(我也忘记这个说法是哪里看到的了),当你使用#include这样的方式时,如同你去青楼,做任何事情都是需要主动的,包括付钱什么的。但是,DI或者IoC这样的却不是,你只需要翻一下牌子,然后太监就用轿子把你想要的送到你的卧榻了,然后完事以后,太监就又把那位姑娘抬走。

OK,下面我也举一些简单例子来说(代码的例子来源于:Patterns of Enterprise Application Architecture这本书籍,书籍有点儿老,但是引用垠神博客的一句话来说,great ideas never die)。


class MyMovieListener {
public Movie[] moviesActedBy(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()]);
}
}


比如这里有一个MyMovieListener类,含有一个由谁扮演的的方法moviesActedBy。而这些电影的查找核心在于了finder,由它去调用findAll方法。

好了,现在你想将finder独立出来,那么你就设计了一个MovieFinder的接口

public interface MovieFinder {
List findAll();
}


代码变为了

class MyMovieListener {
public MyMovieListener() {
finder = new ColonDelimitedMovieFinder("moviestest.txt");
}
private MovieFinder finder;
}


一切都很完美,使用Colon符号分割这个movietest的文本,从而找到我需要的东西。然后突然有一天,你想使用XML来做这件事情,或者换了一个符号进行分割,那么怎么办呢?那么这样的具体实例化,显然不是一件好事,而应该由外面的东西(Assembler,如XML文件等)来负责提供必要信息后,我程序里面自动选择做什么事情,至于怎么做的,你就别管了,你只管翻牌子。这样以后,将会达到不同的图例:




通过DI,就变为这样了






而要完成这样的DI具有多种方式,比如constructor DI, setter DI, interface DI等。如果我的记忆没错的话,你说的spring就是settert DI.(很久没有做Java EE了,所以spring具体方式忘记了,不过DI和IoC的思想让我记忆颇深)。

那么,代码变为这样了:


class MyMovieLister {
public void setFinder(MovieFinder finder) {
this.finder = finder;
}
private MovieFinder finder;
}


class ColonMovieFinder implements MovieFinder {
public void setFilename(String filename) {
this.filename = filename;
}
// .......
}

然后,通过这样的方式,你可以在XML文件里面进行配置








.....



spring快忘光了,应该大致框架如上所示,具体代码你应该比我熟,即通过这样的xml进行插件一样的插入。

那么你所需要做的就是去利用ApplicationContext载入这个XML,随后,通过getBean等方式来做(翻牌子即可,别管框架与容器怎么来做等)。

而#include则大大不同,如你#include “MyClass.h",而MyClass.h有很多方法,如DI之前的图例一般,要做什么,调用MyClass里面的方法,请自己动手,一切主动权在你手中。