首页 > 技术文章 > 浅谈依赖注入(IOC)与控制反转(DI)

TheBob 2018-09-07 16:44 原文

一,定义小王和手机。

小王有逛博客园,淘宝,打手游的习惯(方法)

    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进行了解耦

推荐阅读