<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    wonderer's program

    everything will be better
    posts - 19, comments - 6, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    轉:什么是IOC

    Posted on 2007-10-28 16:50 wonderer 閱讀(686) 評論(0)  編輯  收藏 所屬分類: java

    什么是IOC呢,在網上搜到了一非常有意思的講解。
    IoC就是Inversion of Control,控制反轉。在Java開發中,IoC意味著將你設計好的類交給系統去控制,而不是在你的類內部控制。這稱為控制反轉。

    下面我們以幾個例子來說明什么是IoC

    假設我們要設計一個Girl和一個Boy類,其中Girl有kiss方法,即Girl想要Kiss一個Boy。那么,我們的問題是,Girl如何能夠認識這個Boy?

    在我們中國,常見的MM與GG的認識方式有以下幾種
    1 青梅竹馬; 2 親友介紹; 3 父母包辦
    那么哪一種才是最好呢?

    青梅竹馬:Girl從小就知道自己的Boy。

       1: public class Girl { 
       2:     void kiss(){ 
       3:     Boy boy = new Boy(); 
       4:     } 
       5: }

    然而從開始就創建的Boy缺點就是無法在更換。并且要負責Boy的整個生命周期。如果我們的Girl想要換一個怎么辦?(嚴重不支持Girl經常更換Boy,#_#)

    親友介紹:由中間人負責提供Boy來見面

       1: public class Girl { 
       2:     void kiss(){ 
       3:         Boy boy = BoyFactory.createBoy(); 
       4:     } 
       5: }

    親友介紹,固然是好。如果不滿意,盡管另外換一個好了。但是,親友BoyFactory經常是以Singleton的形式出現,不然就是,存在于Globals,無處不在,無處不能。實在是太繁瑣了一點,不夠靈活。我為什么一定要這個親友摻和進來呢?為什么一定要付給她介紹費呢?萬一最好的朋友愛上了我的男朋友呢?

    父母包辦:一切交給父母,自己不用費吹灰之力,只需要等著Kiss就好了。

       1: public class Girl { 
       2:     void kiss(Boy boy){ 
       3:         // kiss boy 
       4:         boy.kiss(); 
       5:     } 
       6: }

    Well,這是對Girl最好的方法,只要想辦法賄賂了Girl的父母,并把Boy交給他。那么我們就可以輕松的和Girl來Kiss了。看來幾千年傳統的父母之命還真是有用哦。至少Boy和Girl不用自己瞎忙乎了。

    這就是IOC,將對象的創建和獲取提取到外部。由外部容器提供需要的組件。

    我們知道好萊塢原則:“Do not call us, we will call you.” 意思就是,You, girlie, do not call the boy. We will feed you a boy。

    我們還應該知道依賴倒轉原則即 Dependence Inversion Princinple,DIP

    Eric Gamma說,要面向抽象編程。面向接口編程是面向對象的核心。

    組件應該分為兩部分,即 Service, 所提供功能的聲明 Implementation, Service的實現

    好處是:多實現可以任意切換,防止 “everything depends on everything” 問題.即具體依賴于具體。

    所以,我們的Boy應該是實現Kissable接口。這樣一旦Girl不想kiss可惡的Boy的話,還可以kiss可愛的kitten和慈祥的grandmother。
    二、IOC的type

    IoC的Type指的是Girl得到Boy的幾種不同方式。我們逐一來說明。

    IOC type 0:不用IOC

       1: public class Girl implements Servicable { 
       2:     private Kissable kissable; 
       3:     public Girl() { 
       4:         kissable = new Boy(); 
       5:     } 
       6:     public void kissYourKissable() { 
       7:         kissable.kiss(); 
       8:     } 
       9: }

    Girl自己建立自己的Boy,很難更換,很難共享給別人,只能單獨使用,并負責完全的生命周期。

    IOC type 1,先看代碼:代碼

       1: public class Girl implements Servicable { 
       2:  
       3:     Kissable kissable; 
       4:  
       5:     public void service(ServiceManager mgr) { 
       6:         kissable = (Kissable) mgr.lookup(“kissable”); 
       7:     } 
       8:  
       9:     public void kissYourKissable() { 
      10:         kissable.kiss(); 
      11:     } 
      12: }

    這種情況出現于Avalon Framework。一個組件實現了Servicable接口,就必須實現service方法,并傳入一個ServiceManager。其中會含有需要的其它組件。只需要在service方法中初始化需要的Boy。

    另外,J2EE中從Context取得對象也屬于type 1。它依賴于配置文件。

    IOC type 2:

       1: public class Girl { 
       2:  
       3:     private Kissable kissable; 
       4:  
       5:     public void setKissable(Kissable kissable) { 
       6:         this.kissable = kissable; 
       7:     } 
       8:  
       9:     public void kissYourKissable() { 
      10:         kissable.kiss(); 
      11:     } 
      12: }

    Type 2出現于Spring Framework,是通過JavaBean的set方法來將需要的Boy傳遞給Girl。它必須依賴于配置文件。

    IOC type 3:

       1: public class Girl { 
       2:  
       3:     private Kissable kissable; 
       4:  
       5:     public Girl(Kissable kissable) { 
       6:         this.kissable = kissable; 
       7:     } 
       8:  
       9:     public void kissYourKissable() { 
      10:         kissable.kiss(); 
      11:     } 
      12: }
      13:  

    這就是PicoContainer的組件 。通過構造函數傳遞Boy給Girl

    PicoContainer container = new DefaultPicoContainer();
    container.registerComponentImplementation(Boy.class);
    container.registerComponentImplementation(Girl.class);
    Girl girl = (Girl) container.getComponentInstance(Girl.class);
    girl.kissYourKissable();

    參考資料

    1 http://www.picocontainer.org/presentations/JavaPolis2003.ppt
    http://www.picocontainer.org/presentations/JavaPolis2003.pdf

    2 DIP, Robert C Martin, Bob大叔的優秀論文
    http://www.objectmentor.com/resources/articles/dip.pdf

    3 Dependency Injection 依賴注射,Matrin Fowler對DIP的擴展
    http://www.martinfowler.com/articles/injection.html

    4 IOC框架

    PicoContainer 優秀的IOC框架
    http://picocontainer.org/

    Avalon
    http://avalon.apache.org/

    Spring Framework
    http://www.springframework.org/

    HiveMind
    http://jakarta.apache.org/commons/hivemind

    這篇短文基本上是改編自Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern,目的呢,是讓讀者能夠在最短時間內了解IoC的概念。這也是我一貫的“風格”:最短的文字、最精要的內容、最清晰的說明。希望我能做到,自勉^_^


    在J2EE應用開發中,經常遇到的問題就是:如何將不同的組件組裝成為一個內聚的應用程序?IoC模式可以解決這個問題,其目標是將組件的配置與使用分離開。

    IoC,Inversion of Control,控制反轉[1],其原理是基于OO設計原則的The Hollywood Principle:Don't call us, we'll call you。也就是說,所有的組件[2]都是被動的(Passive),所有的組件初始化和調用都由容器負責。組件處在一個容器當中,由容器負責管理。

    要說明IoC模式最好的方法是使用代碼。下邊是一段正常的代碼。

       1: class ClassA...
       2:  
       3:  public String aMethod(String arg){
       4:  
       5:     String result = instanceOfClassB.bMethod();
       6:  
       7:     do something;
       8:  
       9:     return result;
      10:  
      11:  }

    在上邊的代碼里,我們要解決的問題是:ClassA如何獲得ClassB的實例?一個最直接的方法是在aMethod里聲明:

    IClassB instanceOfClassB = new ClassB();

    這里使用了一個接口IClassB。

    問題是,如果出現這樣的情況:繼續使用ClassA,但要求用IClassB的另一個實現ClassB2代替ClassB呢?更概括一點說:ClassA怎樣才能找到IClassB的具體實現?很明顯,上述代碼增加ClassA和ClassB的耦合度,以致于無法在不修改ClassA的情況下變更IClassB的具體實現。

    IoC模式就是用于解決這樣的問題。當然,還有其他的方法,比如Service Locator模式,但現在我們只關注IoC。如前所述,IoC容器負責初始化組件(如IClassB),并將實例交給使用者。使用代碼或配置文件以聲明的方式將接口與實例關聯起來,IoC容器負責進行實際的調用處理。對于調用者,只需要關注接口就行了。

    根據實例傳入方式的不同,IoC分為type 1 IoC(接口注入[3])、type 2 IoC(設值方法注入)和type 3 IoC(構造子注入)。分別用代碼說明如下:

    type 1 IoC(接口注入)

       1: public interface GetClassB {
       2:  
       3:  void getClassB(IClassB instanceOfClassB);
       4:  
       5: }
       6:  
       7: class ClassA implements GetClassB…
       8:  
       9:  IClassB instanceOfClassB;
      10:  
      11:  void getClassB(IClassB instanceOfClassB) {
      12:  
      13: this.instanceOfClassB = instanceOfClassB;
      14:  
      15:  }

    type 2 IoC(設值方法注入)

       1: class ClassA...
       2:  
       3:  IClassB instanceOfClassB;
       4:  
       5:  public void setFinder(IClassB instanceOfClassB) {
       6:  
       7:     this.instanceOfClassB = instanceOfClassB;
       8:  
       9:  }

    type 3 IoC(構造子注入)

       1: class ClassA…
       2:  
       3: ClassB instanceOfClassB;
       4:  
       5:  public classA(IClassB instanceOfClassB) {
       6:  
       7:     this. instanceOfClassB = instanceOfClassB;
       8:  
       9:  }

      Spring使用的是type 2 IoC。


    [1] 在Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern一文中,作者提出本模式更準確的名稱應該是Dependency Injection。考慮到使用上的習慣,在本文檔中我們將繼續使用IoC的概念。

    [2] 同一篇文章中,Martin Fowler還提出了Componet(組件)與Service(服務)的區別問題。我個人認為“組件”更有助于幫助我們理解IoC的概念,所以在本文檔中使用“組件”來代表“組件或服務”

    [3] 如上所述,注入是另一種說法,此處只用于輔助說明。

    主站蜘蛛池模板: 毛片免费在线观看网站| 日日摸夜夜添夜夜免费视频| 亚洲av综合avav中文| 久久国产精品亚洲一区二区| 91天堂素人精品系列全集亚洲| 亚洲国产美女精品久久| 自拍偷自拍亚洲精品播放| 国产真人无码作爱免费视频 | 嫩草影院免费观看| 免费看小12萝裸体视频国产| 亚洲线精品一区二区三区| 亚洲视频一区在线播放| 1000部拍拍拍18免费网站| 免费A级毛片无码久久版| 亚洲视频在线不卡| 4399好看日本在线电影免费| 亚洲乱码中文字幕综合234| 亚洲精品中文字幕无乱码| 一区二区三区免费视频网站| 四虎成年永久免费网站| 亚洲av永久无码精品天堂久久 | 少妇亚洲免费精品| 久久亚洲日韩精品一区二区三区| 亚洲成熟丰满熟妇高潮XXXXX| 免费人成网站在线观看不卡 | 另类免费视频一区二区在线观看| 亚洲国产成人一区二区精品区| 国产偷国产偷亚洲高清在线| 1000部羞羞禁止免费观看视频| 久久精品亚洲乱码伦伦中文| 国产人成亚洲第一网站在线播放| 免费无码av片在线观看| 亚洲综合区小说区激情区| 国产天堂亚洲国产碰碰| 亚洲综合日韩久久成人AV| 九九综合VA免费看| 91亚洲国产在人线播放午夜| 好吊妞在线成人免费| 一级特黄a免费大片| 亚洲字幕在线观看| 亚洲精品A在线观看|