1. 依賴倒置原則(Dependence Inversion Principle,DIP)
High level modules should not depend upon low level modules.Both should depend upon abstractions. Abstractions should not depend upon details should depend upon abstractions
翻譯過來:
n 高層子產品不應該依賴低層子產品,兩者都應該依賴其抽象。
n 抽象不應該依賴細節
n 細節應該依賴抽象
高層子產品和低層子產品容易了解,每一個邏輯的實作都是由原子邏輯組成的,不可分割的原子邏輯就是低層子產品,原子邏輯的再組裝就是高層子產品。細節就是實作類,實作接口或繼承抽象類而産生的類就是細節,其特點就是可以直接被執行個體化,也就是可以加上一個關鍵字new産生一個對象。
依賴倒置原則在java語言中的直接表現就是:
n 子產品間的依賴通過抽象發生,實作類之間不發生直接的依賴關系,其依賴關系是通過接口或抽象類産生的。
n 接口或抽象類不依賴于實作類;
n 實作類依賴接口或抽象類
更加精簡的定義就是“面向接口程式設計”——OOD(Object-Oriented Design,面向對象設計)的精髓之一。
依賴倒置原則是建立在“契約”之上,采用依賴倒置原則可以減少類間的耦合性,提高系統穩定性,降低并行開發引起的風險,提高代碼的可讀性和可維護性。
證明定理是否正确由兩種常用方法:
第一種:根據提出的論題,經過一番論證,推出和定理相同的結論,這是順推證法;
另外一種就是:首先提出命題的僞命題,然後推導出一個荒謬,與已知條件互斥的結論,這是反證法。
如果不使用依賴倒置原則就會加重類間的耦合性,降低系統的穩定性,增加并行開發的風險,降低代碼的可讀性和可維護性。(并發風險:并行開發最大的風險就是風險擴散,本來隻是一段程式的錯誤或異常,就逐漸波及一個功能每一個子產品,甚至到最後毀壞整個項目。)如果兩個類之間有依賴關系,隻要制定出兩者之間的接口(或抽象類)就可以獨立開發了,而且項目之間的單元測試也可以獨立地運作,而TDD(Test-Driver Development,測試驅動開發)開發模式就是依賴倒置原則最進階的應用。(測試驅動開發,先寫好單元測試類,然後再寫實作類,這對提高代碼的品質有非常大的幫助,特别适合研發類項目或項目成員整體水準比較低的情況下使用)
抽象是對實作的限制,對依賴者而言,也是一種契約,不僅僅限制自己,還同時限制自己與外部的關系,其目的就是保證所有細節不脫離契約範疇,確定限制雙方按照既定的契約(抽象)共同發展,隻要抽象這根基線在,細節就脫離不了這個圈圈,始終讓你對象做到“言必信,行必果”。
依賴的三種寫法:
構造函數傳遞依賴對象
在類中通過構造函數聲明依賴對象,按照依賴注入的說法,這種叫構造函數注入。
Setter方法傳遞依賴對象
在抽象中設定Setter方法聲明依賴關系,依照依賴注入的說法,這是Setter依賴注入。
接口聲明依賴對象
在接口的方法中聲明依賴對象。
依賴倒置原則
1. 每個類盡量都由接口或抽象類,或抽象類和接口兩者都具備(有依賴才有依賴倒置)。
接口和抽象類都是屬于抽象的,有了抽象才可能依賴倒置。
2. 變量的表面類型盡量是接口或是抽象類
變量的類型通常是要接口或者抽象類。但是工具類例外,如果使用clone方法,就必須使用實作類,這是JDK提供一個規範。
3. 任何類都是、不應該從具體類派生
項目維護可以不考慮這個規則,維護工作基本就是擴充開發,修複行為,通過一個繼承關系複寫一個方法就可以修正一個很大的bug,何必要繼承最高的基類。
4. 盡量不要複寫基類的方法
如果基類是一個抽象類,而且這個方法已經實作了,子類盡量不要複寫。類間依賴的是抽象,複寫了抽象方法。對依賴的穩定性會造成一定的影響。
5. 結合裡氏替換原則使用。
接口負責定義public 屬性和方法,并且聲明與其他對象的依賴關系,抽象類負責公共的構造步伐的實作,實作類準确的實作業務邏輯,同時在适當的時候對父類進行細化。
依賴倒置就是類間的依賴是确确實實的實作類間的依賴,也就是我們說的面向對象程式設計。而編寫程式需要的就是對現實世界的進行抽象,抽象的結果就是由了抽象類和接口。
這個原則在小項目中難以展現,通常用于比較大的項目,特别是規避一些非技術性因數引起的問題。如果設計優良,代碼結構清晰,人員對項目的影響基本為零。采用依賴倒置可以讓維護人員輕松地擴充和維護。