我們在前文中談過了DI -- Dependency Injection,並且說明了他對解耦合的便利性與重要性。還記得殺手的例子嗎?不記得沒關係,我們來複習一下:
// CoolKiller.java
public class CoolKiller implements Killer{
Weapon weapon;
public CoolKiller(Weapon weapon){
this.weapon = weapon;
}
public void kill() {
weapon.act();
}
}
透過依賴注入,我們可以把武器的『何時使用』和『使用了會怎樣』分別交給Killer和Weapon兩個類別處理。這件事情其實也不是憑空想出來的 -- 我可沒那麼聰明,你知道的。早在2004年,Martin Fowler就提出了想法,他的結論是:『因為依賴物件的獲得被反轉了,所以控制權也被反轉了』。這個重要的觀念,就是我們後來常聽到的解耦合神器:『Inversion of Coltrol (IoC)』。
我知道,我知道直接講這些理論肯定讓你想睡,什麼什麼巴黎鐵塔翻過來又轉過去的。不過聽不懂又有什麼關係,不懂理論又怎樣,只要會用就好了不是嗎?就像上面的殺手範例一樣,那就是IoC的重要實行方法之一。
事情進到了企業級應用程式後有了變化。你可以想像,如果在你的系統哩,每個物件彼此之間都要這樣先new出來再塞進另一個物件,然後再打包塞進第三層物件,雖然這樣也可以達到降耦合的效果,但是你就是會打出很多次『長得很像的程式碼』。其實就是在你的主流程裡面一直new一直new這樣。
『這樣有什麼壞處?』其實沒有。
在你的程式與公司規模都還在學生專案級別時,你當然還是可以在邏輯裡混雜物件創建的處理,這當然沒有差。當你的公司開始走向『企業級』規模時,可就不是這麼一回事了。
企業級Web設計框架Spring可不允許工程師浪費時間再為了每個物件多打這兩三行,他要我們連『這兩三行都省起來』。亦即,他希望工程師只要管主流程的邏輯就好,創物件這種瑣事,讓框架替你完成。怎麼做?Dependency Lookup嚕!
簡單來說,定義好每個物件包含哪些另外的物件 (在Spring容器哩,我們管他叫Bean),定義好後,直接把Spring容器啟動(譬如直接啟動Web Server),Spring會根據你提供的物件定義與彼此間的關係去創造Bean。光說不練可不行,我們來實際操作吧:
// CoolKiller.java
public class CoolKiller implements Killer{
@Autowired
Weapon weapon;
//...Skip the rest
『什麼,就這樣?你囉哩八唆講半天然後寫起來就這樣?』
對啊,就是要讓你知道,雖然背後的原理囉哩八嗦的,但Spring的目的就是要你的自刻程式碼越精簡越好啊!啊不然你還要自己一行一行刻,還要Spring做啥?
所以簡單來說,IoC是概念,他透過反轉控制權的方式來達到降耦合的效果,而DI是一種實作方法,你必須主動創建物件並控制其生命週期,DL則是另一種,框架幫你管理了所有瑣事。