設計模式六大原則(3):依賴倒置原則

前兩回說到設計模式六大模式的兩大心法,那麼幾天我們在看看這個第三大心法:依賴導致原則。

什麼是依賴倒置原則?

定義:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。
心法要訣:這個原則描述的是一個現實當中的事實,即實現都是易變的,而只有抽象是穩定的,所以當依賴於抽象時,實現的變化並不會影響客戶端的調用。

心法適用的場景以及招式:

問題由來:類A直接依賴類B,假如要將類A改爲依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責複雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。
解決方案:將類A修改爲依賴接口I,類B和類C各自實現接口I,類A通過接口I間接與類B或者類C發生聯繫,則會大大降低修改類A的機率。
通俗的栗子:我們現在有個拖拉機A類,直接依賴於B類柴油,沒有熱能,沒有辦法帶動機器運轉呀,所以拖拉機的動能來源就是柴油燃燒產生的熱能轉換機器的動能,可是你光有發動機,沒有輪子怎麼耕地?所以現在A類有依賴C類這個輪子了,所以你的重新設計A類,並加上輪胎才能完成耕地的需求了,可是隨着需求的變更,需要添加更多的拖拉機原件,耙犁,車斗等,A類就變得很龐雜,但是我們將A類編程一個藉口I,讓B類,C類,等元器件全部來實現A類的拖拉機所需要的全部的元器件,這樣整個需求只需要添加接口,實現A類中複雜的邏輯了。

值得注意的是依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象爲基礎搭建起來的架構比以細節爲基礎搭建起來的架構要穩定的多。在java中,抽象指的是接口或者抽象類,細節就是具體的實現類,使用接口或者抽象類的目的是制定好規範和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。


下面我們來實戰:
第一招:舉例子

public class Function02 {
    public static void main(String[] arg0){
        Tractor tractor = new Tractor();
        tractor.dirver(new Oil());
    }
}

class Oil{
    public String getContent(){
        return "拖拉機的動力來源:柴油。。。。";
    }
}

class Tractor{
    public void dirver(Oil oil){
        System.out.println("老司機要開拖拉機了!");
        System.out.println(oil.getContent());
    }
}

運行結果:

老司機要開拖拉機了!
拖拉機的動力來源:柴油。。。。
但是這老司機開的是有輪子的拖拉機,但是這隻有柴油發動機,沒輪子怎麼上路呢?

第二招:在舉栗子:

public class Function02 {
    public static void main(String[] arg0){
        Tractor tractor = new Tractor();
        tractor.dirver(new Oil());
    }
}

class Oil{
    public String getContent(){
        return "拖拉機的動力來源:柴油。。。。";
    }
}

class Tyres{
    public String getContent(){
        return "拖拉機的動力輸出:輪胎。。。。";
    }  
}

class Tractor{
    public void dirver(Oil oil){
        System.out.println("老司機要開拖拉機了!");
        System.out.println(oil.getContent());
    }
}
這可就難住老司機了,當初九沒有設計輪胎安裝位置,有輪胎也是枉然啦!怎麼辦呢?

第三招:拆了重來

public class Function02 {
    public static void main(String[] arg0){
        Tractor tractor = new Tractor();
        tractor.dirver(new Oil());
        tractor.dirver(new Tyres());
        System.out.println("看!老司機上路了。。。");
    }
}

interface ITractor{
        public String getContent();
}

class Oil implements ITractor{
    public String getContent(){
        return "拖拉機的動力來源:柴油。。。。";
    }
}

class Tyres implements ITractor{
    public String getContent(){
        return "拖拉機的動力輸出:輪胎。。。。";
    }
}

class Tractor{
    public void dirver(ITractor iTractor){
        System.out.println("老司機要開拖拉機了!");
        System.out.println(iTractor.getContent());
    }
}

運行結果:

老司機要開拖拉機了!
拖拉機的動力來源:柴油。。。。
老司機要開拖拉機了!
拖拉機的動力輸出:輪胎。。。。
看!老司機上路了。。。
這下進一步設計一個完美的拖拉機標準件接口ITractor,你什麼我就裝什麼,老司機編程老師傅。。。

總結:

傳遞依賴關係有三種方式,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構造方法傳遞和setter方法傳遞,相信用過Spring框架的,對依賴的傳遞方式一定不會陌生。
在實際編程中,我們一般需要做到如下3點:
    低層模塊儘量都要有抽象類或接口,或者兩者都有。
    變量的聲明類型儘量是抽象類或接口。
    使用繼承時遵循里氏替換原則。
依賴倒置原則的核心就是要我們面向接口編程,理解了面向接口編程,也就理解了依賴倒置。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章