首页 > 代码库 > 深入理解DIP、IoC、DI以及IoC容器

深入理解DIP、IoC、DI以及IoC容器

1、依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)。   依赖倒置原则,它转换了依赖,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口

2、控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。

控制反转(IoC),它为相互依赖的组件提供抽象,将依赖(低层模块)对象的获得交给第三方(系统)来控制即依赖对象不在被依赖模块的类中直接通过new来获取。在图1的例子我们可以看到,ATM它自身并没有插入具体的银行卡(工行卡、农行卡等等),而是将插卡工作交给人来控制,即我们来决定将插入什么样的银行卡来取钱。

软件设计原则:原则为我们提供指南,它告诉我们什么是对的,什么是错的。它不会告诉我们如何解决问题。它仅仅给出一些准则,以便我们可以设计好的软件,避免不良的设计。一些常见的原则,比如DRY、OCP、DIP等。

软件设计模式:模式是在软件开发过程中总结得出的一些可重用的解决方案,它能解决一些实际的问题。一些常见的模式,比如工厂模式、单例模式等等。

3、依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。

控制反转(IoC)一种重要的方式,就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现

依赖注入(DI),它提供一种机制,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。通过DI,我们可以在Order类(订单类)的外部将SqlServerDal对象(数据库访问类)的引用传递给Order类对象。根据DIP原则,我们知道高层模块不应该依赖于低层模块,两者应该依赖于抽象。那么构造函数的参数应该是一个抽象类型。

方法一:

  1. 首选,我们需要定义SqlServerDal的抽象类型IDataAccess,并在IDataAccess接口中声明一个Add方法。
    public interface IDataAccess{        void Add();}

     

  2. 然后在SqlServerDal类中,实现IDataAccess接口。
    public class SqlServerDal:IDataAccess{       public void Add()       {           Console.WriteLine("在数据库中添加一条订单!");       }}

     

  3.  接下来,我们还需要修改Order类。
    public class Order{      private IDataAccess _ida;//定义一个私有变量保存抽象              //属性,接受依赖   (也可以构造函数注入)        public IDataAccess Ida       {           set { _ida = value; }           get { return _ida; }       }        public void Add()       {           _ida.Add();       }}

     

     

     

  4. OK,我们再来编写一个控制台程序。
    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace DIPTest{    class Program    {        static void Main(string[] args)        {            SqlServerDal dal = new SqlServerDal();//在外部创建依赖对象            Order order = new Order();//通过构造函数注入依赖            order.Ida = dal;    //给属性赋值            order.Add();             Console.Read();        }    }}

     

  5. 从上面我们可以看出,我们将依赖对象SqlServerDal对象的创建和绑定转移到Order类外部来实现,这样就解除了SqlServerDal和Order类的耦合关系。当我们数据库换成Access数据库时,只需定义一个AccessDal类,然后外部重新绑定依赖,不需要修改Order类内部代码,则可实现Access数据库的操作。
  6. 定义AccessDal类:
    public class AccessDal:IDataAccess{        public void Add()        {            Console.WriteLine("在ACCESS数据库中添加一条记录!");        }}

     

  7. 然后在控制台程序中重新绑定依赖关系:
    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace DIPTest{    class Program    {        static void Main(string[] args)        {             AccessDal dal = new AccessDal();//在外部创建依赖对象               Order order = new Order(dal);//通过构造函数注入依赖                order.Add();             Console.Read();        }    }}

     

方法二:相比构造函数注入和属性注入,接口注入显得有些复杂,使用也不常见。具体思路是先定义一个接口,包含一个设置依赖的方法。然后依赖类,继承并实现这个接口。

  1. 首先定义一个接口IDAO: 
    public interface IDependent{           void SetDependence(IDataAccess ida);//设置依赖项}

     

  2. 依赖类实现这个接口:
    public class Order : IDependent {     private IDataAccess _ida;//定义一个私有变量保存抽象      //实现接口(通过构造函数注入)     public void SetDependence(IDataAccess ida)     {         _ida = ida;     }      public void Add()     {         _ida.Add();     }  }

     

  3. 控制台程序通过SetDependence方法传递依赖:
    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace DIPTest{    class Program    {        static void Main(string[] args)        {            AccessDal dal = new AccessDal();//在外部创建依赖对象          Order order = new Order();             order.SetDependence(dal);//传递依赖             order.Add();             Console.Read();        }    }}

     

IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)。

具体内容参考:http://www.cnblogs.com/liuhaorain/p/3747470.html

深入理解DIP、IoC、DI以及IoC容器