關於IOC和DI的理解

來源:互聯網
上載者:User

IOC:Inversion of Control 控制反轉

DI:Dependency Injection 依賴注入

控制反轉,從字面意思來看,就是控制權又被動變主動,最後又變回被動。

舉個例子:

你的主管要求你做一件事情,這個時候就存在這麼幾個過程,

主管命令你做事情(這個時候主動權在主管,你是被動的)

你接到命令做事情(這個時候主題是你,你是主動的,控制權在你手裡)

你完成事情(這個時候主題依然是你,控制權在你手裡)

報告主管做完事情(主動權又叫交到主管手裡了)

上面的整個過程就完成了一次IOC,從上面可以看出,IOC的基本思想是控制權的轉換過程。

舉個代碼的例子:

假如有Class A,Class B,在A內部會初始化一個B,調用B的一個方法DoMethod

public Class B
{
  public void DoMethod()
  {
    // do somthing;
    }
}

public Class A
{
  public void Excute()
  {
    B b = new B();
     b.DoMethod();
  }
}

 假如在Main函數中如下執行:

  A a = new A();
  a.Excute();

從這兩行代碼來看,事實上也存在一個IOC的過程,a——>b——>a,理解的關鍵點就在在A的內部調用Excute的時候,方法b.DoMethod的執行。

理解了IOC,我們再看一下DI。

從上面A調用B我們可以看出,在初始化一個A的執行個體時,也必須執行個體化一個B,也就是說如果沒有B或者B出了問題,A就無法執行個體化,這就產生了一種依賴,就是A依賴B,這種依賴從設計的角度來說就是耦合,顯然它是無法滿足高內聚低耦合的要求的。這個時候就需要解耦,當然解耦有很多種方法,而DI就是其中一種。不管任何一種解耦方法,都不是說使A和B完全沒有關係,而是把這種關係的實現變得隱晦,不那麼直接,但是又很容易實現,而且易於擴充,不像上面的代碼那樣,直接new一個B出來。

那為什麼我們總是把IOC和DI聯絡到一起呢?是因為DI的基本思想就是IOC,而體現IOC 思想的方法還有另外一個,那就是Service Locator,這個方法好像涉及到的很少。

DI,依賴注入,從字面意思就可以看出,依賴是通過外接注入的方式來實現的。這就實現瞭解耦,而DI的方式通常有三種,

 構造器注入

 屬性設定器注入

 介面注入(我感覺介面注入是同時存在於上兩種注入方式的,而不應該獨立出來)

以上的闡述只是為了先讓我們能對IOC和DI有一個感性的理解,那麼IOC真正解決的問題是什麼呢?

我們講了那麼多主動被動的問題,那我們是從什麼視角來看待這個問題的呢?

所謂為什麼你是主動,而我不是主動呢?這就需要一個參照物,那這個參照物是什麼呢?就是容器,在容器中來體現主動和被動。

用白話來講,就是由容器控製程序之間的關係,而非傳統實現中,由程式碼直接操控。這也就是所謂“控制反轉”的概念所在:控制權由應用代碼中轉到了外部容器,控制權的轉移,是所謂“反轉”,這是通常對IOC的一個解釋。

從容器的角度來看主動和被動,和由容器來控製程序之間的關係,應該是相通的,是一個意思。

IOC要解決的就是程式之間調用的一個問題,它應該是一個思想層面的東西,是一個中心,就像一支樂隊的指揮,而程式就是樂器,通過指揮來協調各種樂器,來演奏出美好的音樂來。

 

以下文字參考:http://www.cnblogs.com/gooddasenlin/archive/2009/03/02/1401631.html

Interface Driven Design 介面驅動

介面驅動有很多好處,可以提供不同靈活的子類實現,增加代碼穩定和健壯性等等,但是介面一定是需要實現的,也就是如下語句遲早要執行:AInterface a = new AInterfaceImp(); 這樣一來,耦合關係就產生了。

如:

Class A
{
   AInterface a;
   A(){}
   aMethod()
   {
     a = new AInterfaceImp();
   }
}

 

ClassA與AInterfaceImp就是依賴關係,如果想使用AInterface的另外一個實現就需要更改代碼了。

當然我們可以建立一個Factory來根據條件產生想要的AInterface的具體實現,即:

InterfaceImplFactory
{
   AInterface create(Object condition)
   {
      if(condition = condA)
        {
          return new AInterfaceImpA();
        }
      elseif(condition = condB)
        {
          return new AInterfaceImpB();
        }
      else
        {
          return new AInterfaceImp();
        }
    }
}

 

表面上是在一定程度上緩解了以上問題,但實質上這種代碼耦合并沒有改變。

通過IoC模式可以徹底解決這種耦合,它把耦合從代碼中移出去,放到統一的XML檔案中,通過一個容器在需要的時候把這個依賴關係形成,即把需要的介面實現注入到需要它的類中,這可能就是“依賴注入”說法的來源了。

IOC模式系統中,通過引入實現IOC模式的IOC容器,即可由IOC容器來管理對象的生命週期、依賴關係等,從而使得應用程式的配置和依賴性規範與實際的應用程式代碼分開。其中一個特點就是通過文本的設定檔進行應用程式組件間相互關係的配置,而不用重新修改並編譯具體的代碼。

當前比較知名的IOC容器有:Pico Container、Avalon 、Spring、JBoss、HiveMind、EJB等。其中,輕量級的有Pico Container、Avalon、Spring、HiveMind等,超重量級的有EJB,而半輕半重的有容器有JBoss,Jdon等。

可以把IoC模式看做是原廠模式的升華,可以把IoC看作是一個大工廠,只不過這個大工廠裡要產生的對象都是在XML檔案中給出定義的,然後利用Java 的“反射”編程,根據XML中給出的類名產生相應的對象。從實現來看,IoC是把以前在Factory 方法裡寫死的對象產生代碼,改變為由XML檔案來定義,也就是把工廠和對象產生這兩者獨立分隔開來,目的就是提高靈活性和可維護性。

IoC中最基本的Java技術就是“反射”編程。反射又是一個生澀的名詞,通俗的說反射就是根據給出的類名(字串)來產生對象。這種編程方式可以讓對象在產生時才決定要產生哪一種對象。反射的應用是很廣泛的,象Hibernate、String中都是用“反射”做為最基本的技術手段。

IoC最大的好處是什嗎?因為把對象產生放在了XML裡定義,所以當我們需要換一個實現子類將會變成很簡單(一般這樣的對象都是現實於某種介面的),只要修改XML就可以了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.