天天看點

七大設計原則(二):依賴倒置原則

參考慕課網視訊《Java設計模式精講》:

視訊作者:Geely

視訊連結:https://coding.imooc.com/lesson/270.html#mid=17149

定義

高層子產品不應該依賴低層子產品,二者都應該依賴其抽象。

強調

抽象不應該依賴細節,細節應該依賴抽象。

針對接口程式設計,不要針對實作程式設計。

優點

可以減少類間的耦合性、提高系統穩定性,提高代碼可讀性和可維護性,可降低修改程式所造成的風險。

案例:清風先生通過看Java視訊來提升自己。

public class JavaVideo {
    //播放的功能
    public void play(){
        System.out.println("看java的視訊");
    }
}
           
public class MrQingFeng {
    //看視訊
    public void watch(JavaVideo video){
        video.play();
    }
}
           

清風先生具有看的功能,并且依賴于JavaVideo這個類。接下來寫測試類。

public class MainTest {
    @Test
    public void testMethod1(){
        MrQingFeng mrQingFeng = new MrQingFeng();
        JavaVideo video = new JavaVideo();
        mrQingFeng.watch(video);
    }
}
           

這段代碼很簡單,結果就是:清風先生通過看Java視訊,成功的提升了自己的Java水準。但是,技術更新疊代很快,現在已經是人工智能和大資料的時代了。是以,清風先生想要開始學習Python這門語言。他還是更加傾向于視訊學習。是以,清風先生想要看Python視訊。但是呢,清風先生家裡的播放器隻支援Java格式的視訊。不支援Python格式的。是以,沒辦法,他就放棄了。

上面的例子,就說明了,清風這個類是個高層子產品,Java視訊是一個低層子產品。他依賴于具體的實作。如果需要看HTML、GO或者其他的視訊,就要更改他所依賴的具體實作。這樣耦合度很大,生産力很低,當需求變更的時候,就要面臨大面積的重構。

是以,下面通過抽象,來解決這個問題。

案例:清風先生想要學習一門程式設計語言,大家都推薦他通過看書來學習,但是他卻不知道應該買什麼書。是以呢,我們就來幫幫他。

定義一個買書的接口:

package com.qfcwx.dependencyinversion;

/**
 * @ClassName: Book
 * @Author: 清風一陣吹我心
 * @Description: TODO 一個買書的接口
 * @Date: 2019/4/7 17:30
 * @Version 1.0
 **/
public interface Book {

    /**
     * 買書
     */
    void buyBook();
}
           

他在B公司的朋友,推薦他買Java的書來學習,因為Java的生态圈已經很完善了。是以,就要定一個類來實作上面的接口。

public class JavaBook implements Book {

    @Override
    public void buyBook() {
        System.out.println("買了一本java語言的書");
    }
}
           

而他在A公司的朋友說現在容器化技術,區塊鍊這麼火。是以推薦他去學習GO語言,他又計劃買GO語言的書。

public class GoBook implements Book {

    @Override
    public void buyBook() {
        System.out.println("買了一本go語言的書");
    }
}
           

人生苦短,我用Python。誰知道,在T公司的女朋友來信了,說現在Python這麼火,不選擇它,還去選别的,是不是今晚想跪鍵盤了?

面對三方面的支援,清風先生可謂舉棋不定啊。沒關系,我們來幫他定。

public class MrQingFeng {

    private Book book;

    public void setBook(Book book) {
        this.book = book;
    }
    //買各種書的方法
    public void buyKindOfBook() {
        book.buyBook();
    }
}
           

想成為一名程式猿,成為一名優秀的程式猿,光掌握一本語言是不夠的,要養成終身學習的習慣。是以,建議清風先生,把每種語言的書都買上,這樣也能解決你現在的糾結情緒,還不用跪鍵盤了。豈不是美哉?

public class MainTest {

    public static void main(String[] args) {
        MrQingFeng mrQingFeng = new MrQingFeng();
        mrQingFeng.setBook(new JavaBook());
        mrQingFeng.buyKindOfBook();

        mrQingFeng.setBook(new PythonBook());
        mrQingFeng.buyKindOfBook();

        mrQingFeng.setBook(new GoBook());
        mrQingFeng.buyKindOfBook();
    }
}
           

看吧,通過依賴抽象的方式,幫清風先生解決了買書的困難。瞬間覺得自己很偉大呢。

言歸正傳,上面的例子,就是強調,我們要面向接口程式設計,不要針對其實作程式設計。若想擴充具體的實作,隻需要實作接口,或者繼承其抽象即可。

例如:清風先生又想買Netty、SpringBoot的書。當然沒問題,隻需要實作買書的接口就行了。不會對應用的整體架構造成影響。

知識擴充

因為清風先生依賴書這個接口,是以,需要将其注入。這裡的注入方式,使用的是Setter方式。

當然還有構造器注入、接口方法注入。

構造器注入

private Book book;
    
    public  MrQingFeng(Book book){
        this.book = book;
    }
    
    public void buyKindOfBook() {
        book.buyBook();
    }    
           

接口方法

public void buyKindOfBook(Book book) {
        book.buyBook();
    }
           

上面說了三種接口注入的方式,在Spring中最常用的就是Setter和構造器注入,也推薦大家使用這兩種方式。

即使想活成強人,也得一步步來不是,别太苦了自己,負面情緒多了就找人宣洩一下,青春加油,未來加油!

繼續閱讀