1. 程式人生 > >依賴倒置原則定義,及倒置的兩種理解

依賴倒置原則定義,及倒置的兩種理解

依賴倒置原則定義

如下(可先不管)
- 高層模組不應該依賴低層模組,兩者都應該依賴抽象
- 抽象不應該依賴細節
- 細節應該依賴抽象

情景描述

當前有一家飲料店,裡面賣著很多飲料

設計如下
這裡寫圖片描述

問題描述

  1. 這裡箭頭符號表示BeverageStore依賴Juice,及高層依賴於低層
  2. 在BeverageStore中,對應的是具體的飲料實現,具體程式碼如下
package headfirst.hd.dep;

public class BeverageStore {

    //賣果汁
    public Juice saleBeverage() {
        //果汁的具體實現
Juice juice = new Juice(); return juice; } }

修改設計,為飲料提供統一介面

備註:這是網上很多教程講的例子,根據我自己的理解,這不是依賴倒置的體現,後來我會給出原因

這裡寫圖片描述
核心程式碼變為一下程式碼,依賴變為不僅依賴低層元件的實現,而且還依賴低層元件的抽象,比之前還更糟糕

package headfirst.hd.dep;

public class BeverageStore {

    //賣果汁
    public Beverage saleBeverage() {
        //果汁的具體實現
Beverage beverage = new Juice(); return beverage; } }

對這個程式碼再優化一下

package headfirst.hd.dep;

//這是網上最常見方式
public class BeverageStore {
    //賣果汁
    public Beverage saleBeverage(Beverage beverage) {
        //做一些其他操作
        return beverage;
    }
}

客戶端Client

package headfirst.hd.dep;

public
class Client { public static void main(String[] args) { BeverageStore store = new BeverageStore(); store.saleBeverage(new Juice()); } }

對應設計變化為
這裡寫圖片描述

  1. 高層依賴低層還是曾在,並且由更高層依賴了低層模組
  2. 我個人覺得這應該叫依賴轉移

引入工廠方法模式改進以上例子

工廠模式設計圖

這裡寫圖片描述

核心程式碼
BeverageStore

package headfirst.hd.dep;

//工廠方法模式
public abstract class BeverageStore {
    //賣果汁
    public Beverage saleBeverage() {
        //直接使用自身定義的抽象方法
        Beverage beverage = createBeverage();
        //做一些其他操作
        return beverage;
    }

    /**
     * 抽象類BeverageStore抽象方法定義,Beverage createBeverage()
     * 表明createBeverage與BeverageStore為一體,關係為一根橫線,
     * 兩者沒有實質依賴關係,因為在BeverageStore中,直接使用自身
     * 定義方法createBeverage,在類BeverageStore的其他方法中,
     * 直接使用該型別,具體實現具體類,延遲到子類
     */
    abstract Beverage createBeverage();
}

BeverageStoreFactory

package headfirst.hd.dep;

//工廠方法模式
public class BeverageStoreFactory extends BeverageStore{

    @Override
    Beverage createBeverage() {
        //可傳入引數,得到更多例項,
        //或者BeverageStoreFactory2,多個工廠方法,都可以
        return new Juice();
    }
}

測試Client

package headfirst.hd.dep;

public class Client {
    //優秀啦,一點都沒有低層模組程式碼
    public static void main(String[] args) {
        BeverageStore store = new BeverageStoreFactory();
        store.saleBeverage();
    }

}

理解加入模式前後的不同

加入前
這裡寫圖片描述
加入後
這裡寫圖片描述

主要區別體現在兩點

  1. store與product關係
    加入工廠前,實際上還是具有依賴關係,實質上將依賴關係往更高層轉移
package headfirst.hd.dep;

//這是網上最常見方式
public class BeverageStore {
    //賣果汁
    public Beverage saleBeverage(Beverage beverage) {
        //做一些其他操作
        return beverage;
    }
}

加入工廠後

//工廠方法模式
public abstract class BeverageStore {
    //賣果汁
    public Beverage saleBeverage() {
        //直接使用自身定義的抽象方法
        Beverage beverage = createBeverage();
        //做一些其他操作
        return beverage;
    }

    /**
     * 抽象類BeverageStore抽象方法定義,Beverage createBeverage()
     * 表明createBeverage與BeverageStore為一體,關係為一根橫線,
     * 兩者沒有實質依賴關係,因為在BeverageStore中,直接使用自身
     * 定義方法createBeverage,在類BeverageStore的其他方法中,
     * 直接使用該型別,具體實現具體類,延遲到子類
     */
    abstract Beverage createBeverage();
}

所有加入前還是具有依賴關係,所以是箭頭,加入工廠模式之後,為介面定義,為一體,所以屬於直線
2. storefactory取代了Client位置
加入前層級關係
這裡寫圖片描述
加入後層級關係
這裡寫圖片描述

倒置的兩種理解

第一種,從設計上理解

這裡寫圖片描述

如果所示,正常都是高層呼叫低層,簡單推理一下

  1. product1(具體的實現)依賴於product(抽象)
  2. 由於引入工廠模式後,store與product為同一關係(同時存在)
  3. 推理出,product1(具體的實現)依賴於store

因此,形成了依賴倒置的現象

第二種,從思想上理解

沒有引入工廠方法模式之前,我們需要一杯果汁(Juice),我們的思路時候這樣的

先有一個飲料店(BeverageStore),然後才會有果汁(Juice),簡單的說就是先有飲料店,最後決定賣什麼飲料

引入工廠方法模式之前,我們需要一杯果汁(Juice),我們的思路時候這樣的
這裡寫圖片描述

先定義飲料介面,後實現具體的飲料店,這些我們可以理解為,我們先選擇什麼要的飲料,最後決定開什麼樣的飲料店

因此,形成了依賴倒置的現象