Spring入門02 - 控制反轉IoC

入門 02 - 控制反轉IoC <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 IoC全名Inversion of Control,如果中文硬要翻譯過來的話,就是「控制反轉」。初看IoC,從字面上不容易瞭解其意義,我覺得要了解IoC,要先從Dependency Inversion開始瞭解,也就是依賴關係的反轉。
 Dependency Inversion在下面這篇文章中有了清楚的解釋:
http://www.objectmentor.com/publications/dip.pdf<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
 簡單的說,在模塊設計時,高層的抽象模塊通常是與業務相關的模塊,它應該具有重用性,而不依賴於低層的實作模塊,例如如果低層模塊原先是軟盤存取模式,而高層模塊是個存盤備份的需求,如果高層模塊直接叫用低層模塊的函式,則就對其產生了依賴關係。
舉個例子,例如下面這個程序:

#include <floppy.h>

....

void save() {

        ....

        saveToFloppy()

    }

}


 由於save()程序依賴於依賴於saveToFloppy(),如果今天要更換低層的存儲模塊爲Usb碟,則這個程序沒有辦法重用,必須加以修改才 行,低層模塊的更動造成了高層模塊也必須跟着更動,這不是一個好的設計方式,我們希望模塊都依賴於模塊的抽象,這樣纔可以重用高層的業務設計。
 如果以對象導向的方式來設計,依賴反轉(Dependency Inversion)的解釋變爲程序不應依賴實作,而是依賴於抽象,實作必須依賴於抽象。我們來看看下面這個Java程序:

BusinessObject.java

public class BusinessObject {

    private FloppyWriter writer = new FloppyWriter();

    ....

  

    public void save() {

        ...

        writer.saveToFloppy();

 

    }

}


 在這個程序中,BusinessObject的存盤依賴於實際的FloppyWriter,如果今天我們想要將存盤改爲存至Usb碟,我們必須修改或繼承BusinessObject進行擴展,而無法直接使用BusinessObject。
如果透過接口的宣告,可以改進此一情況,例如:

public interface IDeviceWriter {

    public void saveToDevice();

}

 

public class BusinessObject {

    private IDeviceWriter writer;

 

    public void setDeviceWriter(IDeviceWriter writer) {

        this.writer = writer;

    }

 

    public void save() {

        ....

        writer.saveToDevice();

    }

}


 這樣一來,BusinessObject就是可重用的,如果今天我有存儲至Floppy或Usb碟的需求,我只要實作IDeviceWriter即可,而不用修改BusinessObject:

public class FloppyWriter implement IDeviceWriter {

    public void saveToDevice() {

        ....

        // 實際儲存至Floppy的程序代碼

    }

}

 

public class UsbDiskWriter implement IDeviceWriter {

    public void saveToDevice() {

        ....

        // 實際儲存至UsbDisk的程序代碼

    }

}


 從這個角度來看,Dependency Inversion的意思即是程序不依賴於實作,而是程序與實作都要依賴於抽象。
 IoC的Control是控制的意思,其實其背後的意義也是一種依賴關係的轉移,如果A依賴於B,其意義即是B擁有控制權,我們要轉移這種關係,所以依 賴關係的反轉即是控制關係的反轉,藉由控制關係的轉移,我們可以獲得組件的可重用性,在上面的Java程序中,整個控制權從實際的 FloppyWriter轉移至抽象的IDeviceWriter接口上,使得BusinessObject、FloppyWriter、 UsbDiskWriter這幾個實現依賴於抽象的IDeviceWriter接口。
 從容器(Container)的角度,程序的業務邏輯部份應是可以重用的,不應受到所使用框架或容器的影響,因爲我們可能轉移整個業務邏輯至其它的框架或容器,如果業務邏輯過於依賴容器,則轉移至其它的框架或容器時,就會發生困難。

 IoC在容器的角度,可以用這麼一句好萊塢名言來代表:"Don't call me, I'll call you." 以程序的術語來說的話,就是「不要向容器要求您所需要的(對象)資源,容器會自動將這些對象給您!」。IoC要求的是容器不侵入應用程序本身,應用程序本身提供好接口,容器可以透過這些接口將所需的資源注至至程序中,應用程序不向容器主動要求資源,故而不會依賴於容器的組件,應用程序本身不會意識到正被容 器使用,可以隨時從容器中脫離轉移而不用作任何的修改,而這個特性正是一些業務邏輯中間件最需要的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章