好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

什么是IoC以及理解为什么要使用Ioc

什么是IoC以及理解为什么要使用Ioc

什么是IoC以及理解为什么要使用Ioc

阅读目录:

一. 一个没有使用IoC的例子

二. 当需求发生变动时,非IoC遭遇到的困境

三. 使用IoC彻底解决问题

四. 总结

一、一个没有使用IoC的例子

IoC的全称是Inversion of Control,中文叫控制反转。要理解控制反转,可以看看非控制反转的一个例子。

 public   class   MovieLister
   {
         public   Movie[] GetMPG(String arg)
       {
             var  finder =  new   ListMovieFinder();
             var  allMovies =  finder.FindAll();

             return  allMovies.Where(m => m.Name.EndsWith( "  .MPG  "  )).ToArray();
       }
   }

 

  public   class   ListMovieFinder
   {
         public  List<Movie>  FindAll()
       {
             return   new  List<Movie> 
                      {
                            new   Movie
                              {
                                  Name  =  "  Die Hard.wmv  "  
                              },
                            new   Movie
                              {
                                  Name  =  "  My Name is John.MPG  "  
                              }
                      };
       }
   } 

 上面的例子中,类MovieLister的作用是列出所有的mpg类型的电影,其中调用了类ListMovieFinder类的方法FindAll()来获取所有的电影。

这段代码看起来还不错,已经符合当前的需求了。

二、当需求发生变动时,非IoC遭遇到的困境

假如,这个时候,movie的列表获取不是直接创建一个list获取,而要求从某个文本文件读取,或者是数据库获取,又或者从web service中获取,我们怎么办?

第一步,再实现一个类, 比如FileMovieFinder,来实现从文本文件中读取Movie列表,再把MovieLister中的这行代码,

     var finder = new ListMovieFinder(); 
替换成

    var finder = new FileMovieFinder(); 
那么这行代码就又能够符合要求了。

新的MovieLister代码是这个样子:

    public   class   MovieLister
   {
         public   Movie[] GetMPG(String arg)
      {
              var  finder =  new   FileMovieFinder();
             var  allMovies =  finder.FindAll();
             return  allMovies.Where(m => m.Name.EndsWith( "  .MPG  "  )).ToArray();
       }
   } 

 如果底层--获取数据的方式不确定,或者经常更改,MovieLister的代码岂不是要频繁改动? 

三、使用IoC彻底解决问题:

MovieLister的功能都是依赖着具体的类,ListMovieFinder,FileMovieFinder。当需求发生变化的时候,就会导致MovieLister的代码也要做相应的改动。

也就是说,MovieLister直接依赖于ListMovieFinder和FileMovieFinder了。

跳出来看,MovieLister的功能只是负责从列表中找出MPG的movie, 至于movie从什么地方来的,不是MovieLister的职责,它也不需要关心。

而解耦合的方法就是”依赖于抽象,而不是依赖于具体”.

(这个例子非常类似于我们的做开发时候的持久层(数据层)和业务逻辑层,其实业务逻辑层也不关心数据是如何提供的,所以业务逻辑层也应当与持久层解耦合。)

实际解决之后的代码:

 public   class   MovieLister
   {
         public   Movie[] GetMPG(String arg)
      {
              var  finder =  MovieFinderFactory.GetFinder();
             var  allMovies =  finder.FindAll();
             return  allMovies.Where(m => m.Name.EndsWith( "  .MPG  "  )).ToArray();
       }
   }
 

  public   class   MovieFinderFactory
{
       public   IMovieFinder GetFinder()
     {
           return   new   FileMovieFinder();
     }
} 

  public   IMovieFinder
{
    List <Movie>  FindAll()
} 

 这里MovieLister就依赖于IMovieFinder接口(依赖抽象), 实际运行时候的实例化由MovieFinderFactory来提供。这样,不同的Movie数据源只需要一个实现IMovieFinder 的类就可以了,不会对MovieLister产生任何影响。

 到这里,实际上已经完成了IoC, 控制权最初取决于MovieLister中是如何实例化MovieFinder 的,现在它已经交出控制权,交由外部来提供具体实例对象了。

这里的MovieFinderFactory就已经是一个简陋的IoC容器功能了。

四、总结

IoC这种解决依赖的方法是面向对象方法的使用。现实世界中,这种方法无处不在。

比如,汽车不会强依赖于某个品牌的轮胎,任何公司生产的轮胎,只要符合汽车的接口,就可以装在这个汽车上使用。

还有电脑的USB接口,只要符合USB标准的外设,就都能够接上电脑使用。

解除依赖不仅让代码结构看起来更加合理,其带来的另一个好处是,各个部分可以单独的做单元测试,使得单元测试能够更加容易的进行。这个对于一些复杂度高的项目,对于保证项目的稳定性和可用性非常有意义。

真正的IoC容器比上面的MovieFinderFactory自然要好用和适用的多。下一篇文章将会介绍一个非常棒的IoC框架Autofac.

相关文章:

理解为什么要使用Ioc

分析Autofac如何实现Controller的Ioc(Inversion of Control)


本文基于 署名 2.5 中国大陆 许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 justrun (包含链接)。如您有任何疑问或者授权方面的协商,请 给我留言 。

 

分类:  IoC

标签:  IOC ,  Autofac

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于什么是IoC以及理解为什么要使用Ioc的详细内容...

  阅读:45次