IoC容器Autofac(1) -- 什么是IoC以及理解為什么要使用Ioc


閱讀目錄:

一. 一個沒有使用IoC的例子

二. 當需求發生變動時,非IoC遭遇到的困境

三. 使用IoC徹底解決問題

四. 總結

一、一個沒有使用IoC的例子

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

public class MPGMovieLister
   {
       public Movie[] GetMPG()
       {
           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"
                              }
                      };
       }
   }

 上面的例子中,類MPGMovieLister的作用是列出所有的mpg類型的電影,其中調用了類ListMovieFinder類的方法FindAll()來獲取所有的電影。

這段代碼看起來還不錯,已經符合當前的需求了。

二、當需求發生變動時,非IoC遭遇到的困境

假如,這個時候,movie的列表獲取不是直接創建一個list獲取,而要求從某個文本文件讀取,或者是數據庫獲取,又或者從web service中獲取,我們怎么辦?

第一步,再實現一個類, 比如FileMovieFinder,來實現從文本文件中讀取Movie列表,再把MPGMovieLister中的這行代碼,

     var finder = new ListMovieFinder();
替換成

    var finder = new FileMovieFinder();
那么這行代碼就又能夠符合要求了。

 

新的MPGMovieLister代碼是這個樣子:

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

 如果底層--獲取數據的方式不確定,或者經常更改,MPGMovieLister的代碼豈不是要頻繁改動? 

三、使用IoC徹底解決問題:

MPGMovieLister的功能都是依賴着具體的類,ListMovieFinder,FileMovieFinder。當需求發生變化的時候,就會導致MPGMovieLister的代碼也要做相應的改動。

也就是說,MPGMovieLister直接依賴於ListMovieFinder和FileMovieFinder了。

跳出來看,MPGMovieLister的功能只是負責從列表中找出MPG的movie, 至於movie從什么地方來的,不是MPGMovieLister的職責,它也不需要關心。

而解耦合的方法就是”依賴於抽象,而不是依賴於具體”.

(這個例子非常類似於我們的做開發時候的持久層(數據層)和業務邏輯層,其實業務邏輯層也不關心數據是如何提供的,所以業務邏輯層也應當與持久層解耦合。)

 

實際解決之后的代碼:

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

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

public interface IMovieFinder
{
    List<Movie> FindAll()
}

 這里MPGMovieLister就依賴於IMovieFinder接口(依賴抽象), 實際運行時候的實例化由MovieFinderFactory來提供。這樣,不同的Movie數據源只需要一個實現IMovieFinder 的類就可以了,不會對MPGMovieLister產生任何影響。

 到這里,實際上已經完成了IoC, 控制權最初取決於MPGMovieLister中是如何實例化MovieFinder 的,現在它已經交出控制權,交由外部來提供具體實例對象了。

這里的MovieFinderFactory就已經是一個簡陋的IoC容器功能了。

 

四、總結

IoC這種解決依賴的方法是面向對象方法的使用。現實世界中,這種方法無處不在。

比如,汽車不會強依賴於某個品牌的輪胎,任何公司生產的輪胎,只要符合汽車的接口,就可以裝在這個汽車上使用。

還有電腦的USB接口,只要符合USB標准的外設,就都能夠接上電腦使用。

 

解除依賴不僅讓代碼結構看起來更加合理,其帶來的另一個好處是,各個部分可以單獨的做單元測試,使得單元測試能夠更加容易的進行。這個對於一些復雜度高的項目,對於保證項目的穩定性和可用性非常有意義。

真正的IoC容器比上面的MovieFinderFactory自然要好用和適用的多。下一篇文章將會介紹一個非常棒的IoC框架Autofac.

 

相關文章:

IoC容器Autofac(2) - 一個簡單示例

IoC容器Autofac(3) - 理解Autofac原理,我實現的部分Autofac功能(附源碼)

IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源碼)

理解為什么要使用Ioc

分析Autofac如何實現Controller的Ioc(Inversion of Control)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM