控制反转和依赖注入理解

一、控制反转(IoC)

1、  IoC是什么

  Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。。Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

  1. 软件系统在没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
  2. 软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。

  通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来

  ●谁控制谁,控制什么:我们直接在对象A内部通过new进行创建对象B,是程序主动去创建依赖对象B(应用程序控制A的依赖对象B的创建);而IoC是有专门一个容器来创建对象B,(Ioc容器来控制对象B的创建);谁控制谁?当然是IoC 容器控制了对象A;控制什么?那就是主要控制了对象A获取依赖对象B手段(不只是对象包括比如文件等)。

  ●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象A中主动控制去直接获取依赖对象B,也就是正转;而反转则是由Ioc容器来帮忙创建A及注入依赖对象B;为何是反转?因为由容器帮我们查找及注入依赖对象B,对象A只是被动的接受依赖对象B,所以是反转;哪些方面反转了?依赖对象B的获取被反转了。

图1 在使用Ioc容器前

图2 在使用Ioc容器后

2、  IoC能做什么

  传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

  其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了


 

二、依赖注入(DI)

1、什么是DI

  DI(Dependency Injection),即“依赖注入”,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

谁依赖于谁:当然是某个容器管理对象依赖于IoC容器;“被注入对象的对象”依赖于“依赖对象”;

为什么需要依赖:容器管理对象需要IoC容器来提供对象需要的外部资源;

谁注入谁:很明显是IoC容器注入某个对象,也就是注入“依赖对象”;

●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

A和B是强耦合时的代码:  

  class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            a.AFunc();
        }
    }
public class A { B b; public A() { b = new B();//在生成A实例的时候直接new出来一个B,A和B强耦合,如果改变B的初始化方法(如变成new B(string bName)),A中的构造器也要随着修改 } public void AFunc() { b.BFunc(); } } public class B { public void BFunc() { Console.WriteLine("B中的方法"); } }

依赖注入的方式对A和B进行解耦:将B对象实例 作为类A的构造器参数进行传入,在调用类A 构造器之前,类B实例已经被初始化好了。像这种非自己主动初始化依赖,而通过外部传入依赖对象的方式,我们就称为依赖注入

 class Program
    {
        static void Main(string[] args)
        {
            B myb = new B();
            A mya = new A(myb);//在A的构造器执行前b的实例已经创建了,B的初始化方法修改为 new B(string bName),A的构造器不用修改
            mya.AFunc();
            Console.ReadKey();
        }
    }

    public class A
    {
        B b;
        public A(B b)
        {
            this.b = b;//B的实例作为参数传入A的构造器
        }
        public void AFunc()
        {
            b.BFunc();
        }
    }

    public class B
    {
        public void BFunc() { Console.WriteLine("B中的方法"); }

    } 

2、IoC和DI的关系

我们已经分别解释了IoC和DI的概念。它们的关系如下:

  • 控制反转是一种思想
  • 依赖注入是一种设计模式

IoC框架使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,例如说ServiceLocator,所以不能将控制反转和依赖注入等同。

参考文章: 

  1、控制反转(IoC)与依赖注入(DI)

  2、我的控制反转,依赖注入和面向切面编程的理解

猜你喜欢

转载自www.cnblogs.com/wyy1234/p/9088186.html