Changes between Initial Version and Version 1 of waue/2011/DI


Ignore:
Timestamp:
Aug 25, 2011, 5:12:22 PM (13 years ago)
Author:
waue
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • waue/2011/DI

    v1 v1  
     1
     2{{{
     3#!html
     4<div style="text-align: center; color:#151B8D"><big style="font-weight: bold;"><big><big>
     5Dependency Injection
     6</big></big></big></div> <div style="text-align: center; color:#7E2217"><big style="font-weight: bold;"><big>
     7Spring 學習
     8</big></big></div>
     9}}}
     10[[PageOutline]]
     11
     12 = Dependency Injection =
     13
     14Spring 所採用的是Dependency Injection 來實現 IoC,中文翻譯為依賴注入
     15
     16依賴注入的意義是:「保留抽象介面,讓組件依賴於抽象介面,當組件要與其它實際的物件發生依賴關係時,藉過抽象介面來注入依賴的實際物件。」
     17
     18依賴注入在Martin Fowler的文章中談到了三種實現方式:
     19 * Interface injection (Type 1 IoC )
     20 * Setter injection (Type 2 IoC )
     21 * Constructor injection ( Type 3 IoC )
     22
     23上面的BusinessObject所實現的是Type 2 IoC,透過Setter注入依賴關係,
     24
     25 == Type 2 IoC : Setter injection ==
     26
     27BusinessObject 依賴於實際的 FloppyWriter,為了讓 BusinessObject 獲得重用性,不讓 BusinessObject 直接依賴於實際的 FloppyWriter,而是依賴於抽象的介面,複習一下 IoC 該節的例子(同上):
     28{{{
     29#!java
     30public interface IDeviceWriter {
     31    public void saveToDevice();
     32}
     33
     34public class BusinessObject {
     35    private IDeviceWriter writer;
     36
     37    public void setDeviceWriter(IDeviceWriter writer) {
     38        this.writer = writer;
     39    }
     40
     41    public void save() {
     42        ....
     43        writer.saveToDevice();
     44    }
     45}
     46
     47public class FloppyWriter implement IDeviceWriter {
     48    public void saveToDevice() {
     49        ....
     50        // 實際儲存至Floppy的程式碼
     51    }
     52}
     53
     54public class UsbDiskWriter implement IDeviceWriter {
     55    public void saveToDevice() {
     56        ....
     57        // 實際儲存至UsbDisk的程式碼
     58    }
     59}
     60
     61}}}
     62
     63如果今天BusinessObject想要與UseDiskWriter物件發生依賴關係,可以這麼建立:
     64{{{
     65#!java
     66businessObject.setDeviceWriter(new UsbDiskWriter());
     67}}}
     68
     69由於BusinessObject依賴於抽象介面,在需要建立依賴關係時,可以透過抽象介面注入依賴的實際物件。
     70
     71 == Type 3 IoC : Constructor injection ==
     72
     73Type 3 IoC,則在是建構式上注入依賴關係,例如:
     74{{{
     75#!java
     76public class BusinessObject {
     77    private IDeviceWriter writer;
     78
     79    public BusinessObject(IDeviceWriter writer) {
     80        this.writer = writer;
     81    }
     82
     83    public void save() {
     84        ....
     85        writer.saveToDevice();
     86    }
     87}
     88}}}
     89
     90Spring 鼓勵的是 Setter injection,但也允許您使用 Constructor injection,使用 Setter 或 Constructor 來注入依賴關係視您的需求而定,使用 Constructor 的好處之一是,您可以在建構物件的同時一併完成依賴關係的建立,然而如果要建立的物件關係很多,則會在建構式上留下一長串的參數,這時使用 Setter 會是個不錯的選擇,另一方面,Setter 可以有明確的名稱可以瞭解注入的物件會是什麼,像是setXXX()這樣的名稱會比記憶Constructor上某個參數位置代表某個物件來得好。
     91
     92 == Type 1 IoC : Interface injection ==
     93
     94Type 1 IoC是Interface injection,使用Type 1 IoC時會要求實作介面,這個介面是為容器所用的,容器知道介面上所規定的方法,它可以呼叫實作介面的物件來完成依賴關係的注入,例如:
     95{{{
     96#!java
     97public interface IDependencyInjection {
     98    public void createDependency(Map dependObjects);
     99}
     100
     101public class BusinessObject implement IDependencyInjection {
     102    private Map dependObjects;
     103
     104    public void createDependency(Map dependObjects) {
     105        this.dependObject = dependObjects;
     106        // 在這邊實現與BusinessObject的依賴關係
     107        ......
     108    }
     109
     110    public void save() {
     111        ....
     112        writer.saveToDevice();
     113    }
     114}
     115
     116}}}
     117如果要完成依賴關係注入的物件,必須實現IDependencyInjection介面,並交由容器管理,容器會呼叫被管理物件的createDependency()方法來完成依賴關係的建立。
     118
     119在上面的例子中,Type 1 IoC要求BusinessObject實現特定的介面,這就使得BusinessObject依賴於容器,如果日後BusinessObject要脫離目前這個容器,就必須修改程式,想想在更複雜的依賴關係中產生更多複雜的介面,組件與容器(框架)的依賴會更加複雜,最後使得組件無法從容器中脫離。
     120
     121所以Type 1 IoC具有強的侵入性,使用它來實現依賴注入會使得組件相依於容器(框架),降低組件的重用性。
     122
     123Spring的核心是個IoC容器,您可以用Setter或Constructor的方式來實現您的業務物件,至於物件與物件之間的關係建立,則透過組態設定,讓Spring在執行時期根據組態檔的設定來為您建立物件之間的依賴關係,您不必特地撰寫一些Helper來自行建立這些物件之間的依賴關係,這不僅減少了大量的程式撰寫,也降低了物件之間的耦合程度。