浅谈依赖注入(IOC)与控制反转(DI)
一,定义小王和手机。
小王有逛博客园,淘宝,打手游的习惯(方法)
class Wang : Person { public string name ;
public int age ; public void blog() { //逛博客园 } public void play() { //玩手游 } public void taoBao() { //淘宝 } }
小王要依赖手机来实现这些功能。
class iPhone6 : Iphone { public string blog(string name) { return name+"逛博客园"; } public string play(string name) { return name+"玩手游"; } public string taoBao(string name) { return name+"逛淘宝"; } }
小王和手机的日常:
class Wang : Person { public string name = "小王"; public int age = 20; public void blog() { //…… 省略若干代码 iPhone6 iphone = new iPhone6(); iphone.blog(name); } public void play() { //…… 省略若干代码 iPhone6 iphone = new iPhone6(); iphone.play(name); } public void taoBao() { //…… 省略若干代码 iPhone6 iphone = new iPhone6(); iphone.taoBao(name); } }
某天小王玩手机
Wang wang = new Wang(); wang.blog(); wang.play(); wang.taoBao();
输出则是
小王逛博客园 小王玩手游 下网逛淘宝
二,小王换手机了。
小王发现手机不好使了,从IPhone6换了一个iPhoneX。
但是他遇到一个问题,就是他之前过度依赖了原来那一部iPhone6,他们之间已经深深耦合在一起了。
如果要换手机,他就要拿起刀来改造自己,把自己体内所有方法中的iphone6 都换成 iphoneX。
经历了漫长的改造过程,小王终于把代码中的 iphone6 全部换成了 iphoneX。虽然很辛苦,但是小王觉得他是快乐的。
但是好景不长,IphoneX被偷走了,为了应急,小王只好重新使用那部刚刚被遗弃的iphone6,但是一想到那漫长的改造过程,小王的心里就说不出的委屈,他觉得自己过于依赖手机了,为什么每次手机出什么问题他都要去改造他自己,这不仅仅是过度耦合,简直是本末倒置,于是他选择交给一个叫"没问题"的第三方公司。
公司告诉他,你不用再控制你的手机了,交给我来管理,把控制权交给我。这就叫做控制反转。
三,"没问题"公司
小王听到了很高兴啊,控制反转就是把手机的控制权从小王的手里交给公司,但是是一种思想罢了,要用什么办法才能实现控制反转呢?
"没问题"公司有“依赖注入” 的核心技术,接下来,"没问题"公司就开始对小王进行改造。
class Wang : Person { public string name; public int age ; private Iphone phone; Wang() { name="小王"; age=20; phone = new Iphone(); } public void blog() { //…… 省略若干代码 phone.blog(name); } public void play() { //…… 省略若干代码 phone.play(name); } public void taoBao() { //…… 省略若干代码 phone.taoBao(name); } }
测试一下新版小王
Iphone iphone = new Iphone(); iphone = new IphoneX(); //创建一个iphoneX的实例 if(iphone.isBroken()) { //如果iphone不可用,则使用旧版手机 iphone = new Iphone6(); } Wang wang = new Wang(iphone);//小王不用关心是什么手机,他只要玩就行了。 wang.blog(); wang.play(); wang.taoBao();
我们先看一下iphoneX 是否可以使用,如果不可以使用,则直接换成iphone6,然后唤醒小王,并把手机塞到他的手里,换句话说,把他所依赖的手机直接注入到他的身上,他不需要关心自己拿的是什么手机,他只要直接使用就可以了。
这就是依赖注入。
四,感悟
如果一个类A 的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题,类A也需要进行改造,如果这样的情况较多,每个类之间都有很多依赖,那么就会出现牵一发而动全身的情况,程序会极难维护,并且很容易出现问题。要解决这个问题,就要把A类对B类的控制权抽离出来,交给一个第三方去做,把控制权反转给第三方,就称作控制反转(IOC Inversion Of Control)。控制反转是一种思想,是能够解决问题的一种可能的结果,而依赖注入(Dependency Injection)就是其最典型的实现方法。由第三方(我们称作IOC容器)来控制依赖,把他通过构造函数、属性或者工厂模式等方法,注入到类A内,这样就极大程度的对类A和类B进行了解耦。