依赖注入和控制反转都是一种设计模式,知乎上看到一则小故事介绍依赖注入和控制反转的概念。
从前有个人叫小明,他喜欢 打游戏、刷抖音、看小电影,小明的伪代码就长这个样子:
classMingextendsPreson{
privateStringname;
privateintage;
publicvoidplay1(){
//打游戏
}
publicvoidplay2(){
//刷抖音
}
publicvoidplay3(){
//看小电影
}
}
小明的这些爱好,他需要依赖一部手机才能实现。于是乎他买了部手机,手机里的功能的伪代码就长这个样子
classIphoneXextendsIphone{
publicStringplayGame(){
return"游戏";
}
publicStringplay2(){
return"抖音";
}
publicStringmovie(){
return"电影";
}
}
小明就把手机牢牢地控制在自己的手里,小明就每天的生活就是:
classMingextendsPreson{
privateStringname;
privateintage;
publicvoidplay1(){
newIphoneX().playGame();//玩游戏
}
publicvoidplay2(){
newIphoneX().play2();//刷抖音
}
publicvoidplay3(){
//看电影
newIphoneX().movie();
}
}
小明每天除了上班,就是回家玩游戏、刷抖音、看电影。随着时间过度,小明的手机越来越卡,卡的玩游戏技能都不能正常释放。没办法小明只好想换个手机,据说新出的小米12不错,硬件不比IphoneX差,关键还是国产性价比贼拉高。于是乎就买了个小米12,于是乎小明就得改造自内部的方法,把IphoneX的内容全部替换成小米12。虽然改造又漫长又痛苦,但是新手机用起来比IphoneX更流畅,小明觉得很开心。
有一天小明在上班的路上,新手机被偷了。没办法暂时只能用回原来的IPhoneX,小明崩溃了,新换的手机,新改的方法,还得把内部的方法改会到原来的IphoneX。小明发现自己对手机的把控太强了,过度依赖,过度耦合,只要换手机,就得把自己内部的方法都得替换一遍。怎么办呢?他不甘心,他向天空大喊,我不要再控制我的手机了。
天空中的造物主听到了他的呼求,告诉他说,你不用再控制你的手机了,交给我来管理,把控制权交给我。这就叫做控制反转。
小明说到,这只是您的想法,一种思想罢了,要用什么办法才能实现控制反转?又可以让我继续使用手机呢?”
造物主不屑的看了一眼小明,扔下了四个大字,“依赖注入!”,“小明,让我来重塑你吧”
classMingextendsPreson{
privateStringname;
privateintage;
privateIphoneiphone;
publicMing(Iphoneiphone){
this.name="小明";
this.age=24;
this.iphone=iphone;
}
publicvoidplay1(){
iphone.playGame();
}
publicvoidplay2(){
iphone.play2();
}
publicvoidplay3(){
iphone.movie();
}
}
从此以后,小明的一点也不关心自己拿的是什么手机,他只要直接使用就可以了。往后的每一天他就是这样过的:
//创建个手机的实例
Iphoneiphone=newIphoneX();
if(iphone.isBreak()){
iphone=newXiaoMi12();//如果IphoneX坏了,就小米12
}
Mingming=newMing(iphone);
ming.play1();
ming.play2();
ming.play3();
如果一个类A 的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题,类A也需要进行改造,如果这样的情况较多,每个类之间都有很多依赖,那么就会出现牵一发而动全身的情况,程序会极难维护,并且很容易出现问题。要解决这个问题,就要把A类对B类的控制权抽离出来,交给一个第三方去做,把控制权反转给第三方,就称作控制反转(IOC Inversion Of Control)。控制反转是一种思想,是能够解决问题的一种可能的结果,而依赖注入(Dependency Injection)就是其最典型的实现方法。由第三方(我们称作IOC容器)来控制依赖,把他通过构造函数、属性或者工厂模式等方法,注入到类A内,这样就极大程度的对类A和类B进行了解耦。