到底是什么东西的控制被反转了呢?对应到前面的例子

时间:2022-03-15 02:38:39

2006年多部贺岁大片以让人应接不暇的频率络绎不绝,此中张之亮的《墨攻》算是对照出彩的一部,讲述了战国时期墨家人革离辅佐梁

国抵挡赵国侵略的小我私家英雄主义故事,恢宏壮阔,浑雄凝重的历史局面相当震撼。此中有一个场景:当刘德华所饰的墨者革离达到梁都城城

下,城上梁国守军问:“来者何人?”,刘德华回答:“墨者革离!”,我们不妨事用C#(原文是java,我改削)对这段“城门问对”的场景进行编剧并借由这个例子来理解IoC的内涵。

剧本和扮演者耦合

MoAttack代表《墨攻》的剧本,cityGetAsk()代表“城门问对”这段剧情,LiuDeHua是具体扮演者刘德华:

代码清单1

public class MoAttack {

public MoAttack() {}

public void cityGateAsk(){

LiuDeHua ldh = new LiuDeHua(); ① 演员直接侵入剧本

ldh.responseAsk("墨者革离!");

}

}

我们会发明以上剧本在①处,作为具体扮演者的刘德华直接侵入到剧本中,使剧本和演员直接耦合在一起:

图(1)剧本与演员直接耦合

一个明智的编剧在剧情创作时应围绕故事的角色进行,而不应考虑角色的具体扮演者,这样才可能在剧本投拍时*地选择任何适合的演员,而非绑定在刘德华一人身上。通过以上的分析,我们知道需要为该剧本主人公革离界说一个接口,以角色进行剧情布置,扮演者实现角色的接口:

代码清单2 MoAttack:引入剧本角色

public class MoAttack{

public MoAttack() {}

public void cityGateAsk()

{

GeLi geli = new LiuDeHua(); ① 引入革离角色接口

geli.responseAsk("墨者革离!"); ② 通过接口开展剧情

}

}

在①处引入了剧本的角色——革离,剧本的情节通过角色展开,在拍摄时角色的事迹由演员表示,,如②地方示。因此剧本、革离、刘德华三者的类图关系如图2所示:

到底是什么东西的控制被反转了呢?对应到前面的例子

图2剧本、革离、刘德华三者的类图关系

我们但愿剧本和演员无关,可是,在图2中,我们看到MoAttack同时依赖于GeLi接口和LiuDeHua类,并没有到达我们所期望的剧本仅依赖于角色的目的。可是角色最终又必需通过具体的演员才华完成拍摄,如何将让LiuDeHua和剧本无关而又能完成GeLi的具体行动呢?固然是在影片投拍时,导演将LiuDeHua布置在GeLi的角色上,通过导演之手将剧本、角色、扮演者装配起来。

到底是什么东西的控制被反转了呢?对应到前面的例子

图3剧本和扮演者解耦了

通过引入导演,剧本和具体的扮演者解耦了,对应到软件中,导演象是一个装配器,将具体的扮演者赋给了剧本的角色。

此刻我们可以反过来讲解IOC的观点了。IOC(Inverse of Control)的字面意思是控制反转,它包孕两个层面的内容:其一是“控制”,其二是“反转”,到底是什么对象的控制被反转了呢?对应到前面的例子, “控制”是指GeLi角色饰演者的选择控制权,“反转”是指这种选择控制权从《墨攻》剧本中移除,转交到导演的手中。对付措施来说,便是某一接口具体实现类的选择控制权从客户类中移除,转交给第三方来确定,客户类不知道是哪个具体的实现类,它通过接口要领对实现类进行挪用。

因为IOC确实不够开门见山,因此业界曾进行了广泛的讨论,最终软件界的泰斗级人物Martin Fowler提出了DI(依赖注入:Dependency Injection)的观点,即将客户类对接口实现类的依赖关系由第三方(容器或协作类)注入,以移除客户类对具体接口实现类的依赖。“依赖注入”的观点显然比“控制反转”直接达意,易于理解。

IOC的三种类型

从注入要领上看,主要可以划分为三种的注入类型,分袂是结构函数注入、属性注入和接口注入,Spring.Net撑持结构函数注入和属性注入。下面我们继续使用以上的例子说明这三种注入要领的区别。

结构函数注入

我们通过客户类的结构函数,将接口实现类通过接口变量传入,如代码清单3所示:

代码清单3 MoAttack:通过结构函数注入革离饰演者

public class MoAttack{

public MoAttack(){}

private GeLi geli;

public MoAttack(GeLi geli){ ① 注入革离的具体饰演者

this.geli = geli;

}

public void cityGateAsk()

{

geli.responseAsk(“墨者革离!”);

}

}

MoAttack的结构函数不关心具体是谁饰演革离这个角色,只要在①处传入的饰演者按剧本要求完成角色成果即可。

角色的具体饰演者由导演来布置,如代码清单4所示:

代码清单 4 Director:通过结构函数注入革离饰演者

public class Director {

public void direct(){

GeLi geli = new LiuDeHua(); ① 指定角色的饰演者

MoAttack moAttack = new MoAttack(geli); ② 注入具体饰演者到剧本中

moAttack.cityGateAsk();

}

}

属性注入