設(shè)計(jì)模式之三依賴倒置原則(DIP)

依賴倒置(Dependence Inversion Principle,DIP)

High level modules should not deppend oupon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

定義中有三層含義:

  • 高層模塊不應(yīng)該依于低層模塊,兩者都應(yīng)該依賴于其抽象。
  • 抽象不應(yīng)該依賴細(xì)節(jié)。
  • 細(xì)節(jié)應(yīng)該依賴抽象。
    理解: 高層模塊相對(duì)低層模塊而言。低層模塊是不可細(xì)分的原子邏輯模塊。其組裝即是高層模塊。
    面向?qū)ο蟮恼Z言中,抽象就是接口或者抽象類,不能被實(shí)例化。細(xì)節(jié)就是繼承抽象類或?qū)崿F(xiàn)接口而產(chǎn)生的類,可以被實(shí)例化。
    java中依賴倒置原則的體現(xiàn):
    1. 模塊之間的依賴通過抽象發(fā)生,實(shí)現(xiàn)類直接不直接發(fā)生依賴關(guān)系,依賴是通過接口和抽象類產(chǎn)生的。
    2. 接口和抽象類不依賴于實(shí)現(xiàn)類
    3. 實(shí)現(xiàn)類依賴于借口或者抽象類
    即--面向接口編程 。
    案例分析:程序員一般都是多技能型的,在工作時(shí)會(huì)使用多種編程語言,不同語言的代碼會(huì)以不同的語法運(yùn)行。因此有這么一個(gè)業(yè)務(wù)場(chǎng)景,程序員使用不同的語言進(jìn)行編程,代碼以不同的語法運(yùn)行。
    這里有三類對(duì)象,編程語言-程序員-業(yè)務(wù)場(chǎng)景


    image.png

    代碼:

Coder.java
public class Coder {
    public void code(Java java){
        java.run();
    }
}
Java.java
public class Java {
    public void run(){
        System.out.println("代碼以Java的語法運(yùn)行~");
    }
}
Client.java
public class Client {
    public static void main(String[] args) {
        Coder coderA = new Coder();
        Java java = new Java();
        coderA.code(java);
    }
}

這里存在一個(gè)問題,如果我們的系統(tǒng)擴(kuò)展的比較大:存在多種程序員,如后端工程師,前端工程師,每種程序員的技術(shù)棧不一樣,每種語言的語法也都不一樣,那我們的程序員Coder類的code方法需要根據(jù)語言的不同重載很多個(gè)版本才能滿足程序員使用多種語言進(jìn)行編程的需求。這樣一來,每次增加一種程序員,我們需要根據(jù)其技能增加code的重載方法;每次增加一種語言,我們需要相應(yīng)地?cái)U(kuò)充使用它的程序員的相關(guān)方法。ade,殺一個(gè)產(chǎn)品經(jīng)理祭天,這么頻繁變態(tài)的需求。

貫徹依賴倒置的原則,解決方案應(yīng)該是這樣的:

image.png
ICoder.java 程序員接口
public interface ICoder {
    public void code(ILang iLang);
}
ILang.java 語言接口
public interface ILang {
    void runWithSyntax();
}
CoderA.java A類型程序員
public class CoderA implements ICoder {
    @Override
    public void code(ILang iLang) {
        iLang.runWithSyntax();
    }
}
Java.java java語言
public class Java implements ILang {
    @Override
    public void runWithSyntax() {
        System.out.println("程序以Java的語法運(yùn)行");
    }
}
Lisp.java lisp語言
public class Lisp implements ILang {
    @Override
    public void runWithSyntax() {
        System.out.println("程序以Lisp的語法運(yùn)行");
    }
}
Client.java 業(yè)務(wù)場(chǎng)景類
public class Client {
    public static void main(String[] args) {
        ICoder coder = new CoderA();
        ILang lang = new Java();
        coder.code(lang);
    }
}

這樣的解決方案的好處是:當(dāng)新增低層模塊時(shí),不需要修改與其平行的模塊,只需要修改業(yè)務(wù)場(chǎng)景類,即高層模塊即可,更利于拓展系統(tǒng)。
上面的代碼里面新增Lisp類以后,直接在Client類里面使用ILang lang = new Lisp();即可,程序員就能使用Lisp的語法進(jìn)行編程了。避免去修改程序員類的相關(guān)方法。程序應(yīng)該是面向拓展的而不是面向修改的。

依賴傳遞的三種方法

  1. 通過構(gòu)造方法傳遞
    在需要注入接口的類中聲明接口,然后通過構(gòu)造方法的參數(shù)初始化。在調(diào)用的時(shí)候直接傳入一個(gè)接口的實(shí)現(xiàn)類即可。
  2. Setter方法傳遞
    和構(gòu)造方法注入相似。
  3. 接口注入
    形同這樣的方式是接口注入: ILang lang = new Java();

晚安各位?。?!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容