從面向對象編程的觀點來解釋ID:算法
Collaborating classes should rely on the infrastructure to provide the necessary services.數據庫
依賴注入是一系列設計模式和原則,用於開發鬆散耦合的程序。編程
最基本的目的:可維護性。設計模式
大多數編程技術的目的是儘量高效率地提供可工做的程序。其中一個目的就是編寫可維護性的代碼。ide
使代碼容易維護的一種方式就是鬆散耦合。鬆散耦合使代碼具備可擴展性,可擴展性使代碼具備可維護性。函數
四大誤解單元測試
DI廣泛用於延遲綁定測試
DI廣泛用於單元測試spa
DI是一種抽象工廠設計
DI須要DI容器
延遲綁定
延遲綁定是一種不須要從新編譯代碼就能替換應用程序一部分的能力。
DI能提供延遲綁定,但二者不能劃等號。
一種抽象工廠
不少人將DI當作一種服務,用於裝載別的服務,也就是服務裝載着(Service Locator)。但這是DI的對立面。
DI容器
DI容器是一個可選庫,方便咱們組合組件,但這不是必須的。
DI的目標
替換原則,DI最重要的軟件設計原則。
在軟件設計中,實現同一接口的一個實現攔截另外一個實現,這個叫作裝飾者模式。它能使咱們引進新的特性和方面而不用重寫原有的代碼。
另外一種給現有代碼增長新功能的方式是對接口的當前實現用一個新的實現替代。組合模式?
還有一種就是用到了適配器模式。
使用DI的好處
延遲綁定
到運行時才肯定類型。
可擴展性
使用裝飾模式來增長可擴展性。好比有一個Interface IWriteMessage,已經有一個ConsoleWriteMessage實現了這個接口,在Console中打印消息,如今須要增長一個Authentication,那麼能夠另外定義一個類AuthenticationWriteMessage類,它也實現IWriteMessage接口,同時它的構造函數接受一個IWriteMessage類型,在接口的方法中增長要擴展的功能,而後調用構造函數接受的類型的方法。
這個實現了開閉原則。 COMPOSITION ROOT
同時,ConsoleWriteMessage類實現最終功能,AuthenticationWriteMessage類實現驗證,分離關注點。
並行開發
分離關注點後,功能能夠交給不一樣的開發團隊並行開發。
可維護性
每一個類的職能清晰定義並受到限制,維護就變的簡單多了。
這是單一職能原則。
可測試性(指單元測試)
由於遵照了依賴倒置原則,因此單元測試很容易實現。
Test Doubles
什麼該注入,什麼不應注入
.NET Base Library定義了不少類型,咱們引用一個程序集,而後使用其中的類型。這樣是否是就是增長了耦合度?
把依賴分紅穩定依賴(Stable Dependency)和可變依賴(Volatile Dependency)頗有幫助。
穩定依賴
BCL的不少模塊都不會增長應用程序的耦合度。它們提供了可重用的功能來使你的代碼簡潔。
默認的,你能夠把幾乎全部定義在BCL中的類型都認爲是穩定依賴。
穩定依賴的評判標準
類或模塊已經存在
你預期新版本不會有破壞性的改變
算法是固定的
你不會考慮去替換這個類或模塊
可變依賴
判斷標準
依賴引入了這樣一個需求,須要爲程序建立和配置運行時環境。關係型數據庫就是一個很好的例子。這種類型缺乏延遲綁定和可擴展性,使得可測試性困難。
依賴並不存在,可是它存在於開發中。一個明顯的症狀就是不能並行開發。
依賴不能安裝在開發組織的全部機器上。好比昂貴的第三方組件。
依賴包含不肯定性的行爲。
DI的邊界
將建立依賴的職責從類中移出,雖然類不能對建立的過程再作控制,可是咱們開發人員能夠。並且咱們能夠統一建立依賴的方式。
對象組合、攔截和生命週期管理是DI的三個方面。
對象組合
爲了得到可擴展性、延遲綁定和並行開發的好處,咱們使用對象組合。剛開始,DI就等同於對象組合。
對象生命週期
使用依賴注入,對象放棄了建立依賴的權利,同時也放棄了控制依賴生命週期的權利。.NET的垃圾收集器會幫咱們處理。
依賴能夠爲各個對象分別建立,也能夠共享給各個對象。因此對象不須要控制依賴的生命週期。
若是依賴實現了IDispose接口,事情會變得比較複雜(第八章)。
攔截
當咱們把對依賴的控制交給第三方,咱們就有了在把依賴傳給對象前對其進行修改的權利。也就是使用裝飾模式。
經過使用攔截,咱們獲得了方面編程的能力。