依賴注入(DI)是控制反轉(IoC)的一種方式。


那么在IoC模式中,被注入對象又是通過那些方式來通知 IoC Service Provider為起提供服務的呢?
三種依賴方式:構造函數方法注入、Setter方法注入與接口注入。
構造函數方法注入:

setter方法注入:


接口注入:


參考:書籍《spring揭秘》
參考博客:https://www.cnblogs.com/weidagang2046/archive/2009/12/10/1620587.html
那么依賴注入對象與我們自己創建對象,到底應該是一種怎樣的關系呢?
DI和對象創建誰也不能取代誰,應該根據情況采用合理的設計。那么我們自然要問,合理的標准在哪里呢,有沒有明確的指導方針供我們設計時參考呢?答案是有!那就是對象間關系。在OO中,對象間關系的大致可分為兩類:縱向關系和橫向關系。縱向主要指繼承關系,比較容易區分;但橫向關系比較微妙。從本文的例子中我們已經明顯感覺到了橫向關系是需要仔細區分的。
按UML建議橫向關系大體分為4種,它們的耦合程度由弱到強:
依賴 < 關聯 < 聚合 < 組合
1. 依賴(Dependency):語義“a uses b”,a依賴於b,但不持有b的引用;比如:現實世界的例子有“人對空氣的依賴關系”,在程序中a.f(b)可以理解為a對b的依賴(或者說對b的類型B的依賴),b作為a的方法參數,a內部成員變量不引用b。
2. 關聯(Association):語義“a has b”,a擁有b的引用,但a和b無從屬關系,二者是一種松散的關聯關系,可以隨時解除或建立;比如本文中“人與汽車關系”。
3. 聚合(Aggregation):語義“a owns b”,a擁有b的引用,且有從屬關系,二者的耦合比關聯更強,但a並不負責b的生命周期。在程序中,b並非a專有的內部實現細節;除a以為,外部也可能引用b。比如,”汽車和輪胎關系”,汽車不負責輪胎的生產,汽車報廢了輪胎或許還可以繼續使用。
4. 組合(Composition):語義“b is a part of a”,a不僅擁有b的引用,還應該全權負責b的整個生命周期,在程序中b通常是a的內部實現細節,不暴露給外部;比如本文中人與心臟的關系。
我們注意這四種關系中有一個關鍵的概念“對象生命周期”,在建模時辨別清楚對象生命周期就不難選擇采用DI還是創建對象。DI意味着使用者不負責依賴對象的生命周期,創建對象則相反。對應到上面的4種橫向關系,我們一般可以這樣處理:第1種依賴關系不需要DI也不需要創建對象;第2,3種關聯和聚合關系適合采用DI方式,最后一種組合關系適合采用創建對象方式。
注入方式的比較我們也討論了,那么構造函數與setter在什么樣的情況下適合呢?
通過具體例子來體會二者的區別:“人與身份證的依賴關系”適合采用Setter注入,因為人不是一出生就有身份證,而是到了法定年齡才有,用構造函數注入表達的語義與此相違背。相反“人與父母的依賴關系”則適合采用構造函數注入,因為親子關系是從人一出生就建立的,用Setter注入必然使得對象創建后有一段時間處於非法狀態,按契約式設計的術語即破壞了對象的不變量(invariant)。
