依賴倒置原則
依賴倒置原則的原始定義是:
● 高層子產品不應該依賴低層子產品,兩者都應該依賴其抽象;
● 抽象不應該依賴細節;
● 細節應該依賴抽象。
那什麼是抽象?什麼又是細節呢?
---->在Java語言中,抽象就是指接口或抽象類,兩者都是不能直接被執行個體化的;細節就是實作類,實作接口或繼承抽象類而産生的類就是細節,其特點就是可以直接被執行個體化,也就是可以加上一個關鍵字new産生一個對象。依賴倒置原則在Java語言中的表現就是:
● 子產品間的依賴通過抽象發生,實作類之間不發生直接的依賴關系,其依賴關系是通過
接口或抽象類産生的;
● 接口或抽象類不依賴于實作類;
● 實作類依賴接口或抽象類。更加精簡的定義就是“面向接口程式設計”——OOD(Object-Oriented Design,面向對象設
計)的精髓之一。
依賴倒置的優點
---->減少類間的耦合性
---->提高系統的穩定性
---->降低并行開發引起的風險
---->提高代碼的可讀性和可維護性。
證明一個定理是否正确,有兩種常用的方法:一種是根據提出的論題,經過一番論證,推出和定理相同的結論,這是順推證法;還有一種是首先假設提出的命題是僞命題,然後推導出一個荒謬、與已知條件互斥的結論,這是反證法。我們今天就用反證法來證明依賴倒置原則是多麼優秀和偉大
論題:依賴倒置原則可以減少類間的耦合性,提高系統的穩定性,降低并行開發引起的風險,提高代碼的可讀性和可維護性。
反論題:不使用依賴倒置原則也可以減少類間的耦合性,提高系統的穩定性,降低并行開發引起的風險,提高代碼的可讀性和可維護性。
Driver類
package com.yeepay.sxf.sj4;
/**
* 司機
* @author sxf
*
*/
public class Driver {
public void dirverCar(Benchi benchi){
System.out.println("Driver.dirverCar(人開車)");
benchi.run();
}
}
Car類
* 奔馳
public class Benchi {
public void run(){
System.out.println("Benchi.run(奔馳奔跑)");
Client類
public static void main(String[] args) {
Benchi vBenchi=new Benchi();
Driver diiDriver=new Driver();
diiDriver.dirverCar(vBenchi);
(1)如果人再想開寶馬,則不靈活。耦合度大。抽象,面向接口程式設計,可以降低耦合度。
(2)大型項目。人分子產品開發。高子產品,不需要等待低子產品開發完成,才能開發。隻需要低子產品的接口即可。
抽象是對實作的限制,對依賴者而言,也是一種契約,不僅僅限制自己,還同時限制自己與外部的關系,其目的是保證所有的細節不脫離契約的範疇,確定限制雙方按照既定的契約(抽象)共同發展,隻要抽象這根基線在,細節就脫離不了這個圈圈,始終讓你的對象做到“言必信,行必果”。
依賴的三種寫法
第一:構造函數傳遞依賴對象
第二:Setter方法傳遞依賴對象
第三:接口聲明依賴對象
最佳實踐
依賴倒置原則的本質就是通過抽象(接口或抽象類)使各個類或子產品的實作彼此獨立,不互相影響,實作子產品間的松耦合,我們怎麼在項目中使用這個規則呢?隻要遵循以下的幾個規則就可以:
● 每個類盡量都有接口或抽象類,或者抽象類和接口兩者都具備
-->這是依賴倒置的基本要求,接口和抽象類都是屬于抽象的,有了抽象才可能依賴倒置。
● 變量的表面類型盡量是接口或者是抽象類
-->很多書上說變量的類型一定要是接口或者是抽象類,這個有點絕對化了,比如一個工具
類,xxxUtils一般是不需要接口或是抽象類的。還有,如果你要使用類的clone方法,就必須
使用實作類,這個是JDK提供的一個規範。
● 任何類都不應該從具體類派生
-->繼承不得到超過兩層。事無絕對。但可以追求完美。
● 盡量不要覆寫基類的方法
-->如果基類是一個抽象類,而且這個方法已經實作了,子類盡量不要覆寫。類間依賴的是抽象,覆寫了抽象方法,對依賴的穩定性會産生一定的影響。
● 結合裡氏替換原則使用