嘻哈說:設計模式之依賴倒置原則

一、定義

按照慣例,首先咱們來看一下依賴倒置原則的定義。html

抽象不該該依賴於細節,細節應當依賴於抽象。 換言之,要針對接口編程,而不是針對實現編程。程序員

爲何要這樣說呢?編程

由於細節具備易變性,很是的不穩定。不少時候,需求改變就會給細節帶來改變。bash

而抽象則是相對穩定的,抽象是從衆多的事物中抽取出共同的、本質性的特徵,是比較難被改變的。app

因此,咱們確定要選擇對抽象編程,而不選擇對細節編程。框架

抽象在Java中則指的是抽象類或者接口;細節則是表明着具體實現。ide

對接口編程,是寫出健壯性代碼的根本,是優秀程序員必備的基本素質。學習

二、含義

一、高層模塊不該該依賴低層模塊,二者都應該依賴其抽象ui

不管是高層模塊,仍是低層模塊,所有都屬於具體的實現,屬於細節,而細節確定是不能相互依賴的。this

他們都應該依賴於抽象。

二、抽象不該該依賴細節

都不該該依賴於細節,特別是抽象更加不該該依賴細節。

三、細節應該依賴抽象

都應該依賴抽象,細節依賴抽象,抽象也依賴抽象。

三、代碼

一、接口方法中聲明依賴對象

package com.fanqiekt.principle.inversion;

/**
 * 廚師接口
 *
 * @author 番茄課堂-懶人
 */
public interface IChef {

    /**
     * 作飯
     */
    void cooking();
}
複製代碼

廚師都會作飯。

package com.fanqiekt.principle.inversion;

/**
 * 四川廚師
 *
 * @author 番茄課堂-懶人
 */
public class SiChuanChef implements IChef {

    @Override
    public void cooking() {
        System.out.println("四川廚師作飯,多放辣椒。");
    }
}
複製代碼

廚師的實現類,川菜廚師,其中的邏輯都屬於細節,例如川菜廚師有本身作飯的套路(不能沒有辣)。

package com.fanqiekt.principle.inversion;

/**
 * 山東廚師
 *
 * @author 番茄課堂-懶人
 */
public class ShanDongChef implements IChef {

    @Override
    public void cooking() {
        System.out.println("山東廚師作飯,用蔥薑蒜。");
    }

}
複製代碼

另外一個廚師的實現類,魯系廚師,魯菜廚師也有本身作飯的套路(善用蔥薑蒜)。

package com.fanqiekt.principle.inversion;

public interface IWaiter {

    /**
     * 點餐
     * @param chef 指定作飯的菜系廚師
     */
    void order(IChef chef);
}
複製代碼

服務員的抽象接口,服務員都須要爲客人點餐。

order(IChef chef) 方法就是接口方法中聲明依賴對象。

在接口中定義該方法,並將依賴的抽象對象做爲參數傳入。

package com.fanqiekt.principle.inversion;

/**
 * 接口方法中聲明依賴對象
 *
 * @author 番茄課堂-懶人
 */
public class Waiter implements IWaiter{

    @Override
    public void order(IChef chef){
        if(chef!=null) {
            chef.cooking();
        }

    }

}
複製代碼

服務員的實現類,點餐是讓傳入的廚師去作飯。

IChef sichuanChef = new SiChuanChef();
IChef shandongChef = new ShanDongChef();
IWaiter waiter = new Waiter();
waiter.order(sichuanChef);
waiter.order(shandongChef);
複製代碼

將抽象對象做爲order方法參數。

四川廚師作飯
山東廚師作飯
複製代碼

運行結果。

每次調用方法時,都傳入依賴對象。

優勢是靈活,每次均可以傳入不一樣的依賴對象。

缺點是繁瑣,每次都須要傳入依賴對象。

二、構造方法傳遞依賴對象

package com.fanqiekt.principle.inversion;

public interface IWaiter {

    /**
     * 點餐
     */
    void cooking();
}
複製代碼

服務員接口修改:cooking方法去掉參數。

package com.fanqiekt.principle.inversion;

/**
 * 構造方法傳遞依賴對象
 *
 * @author 番茄課堂-懶人
 */
public class Waiter implements IWaiter {

    private IChef chef;

    /**
     * 構造方法中傳入依賴的抽象對象
     * @param chef 廚師抽象接口
     */
    public Waiter(IChef chef){
        this.chef = chef;
    }

    @Override
    public void cooking(){
        if(chef!=null) {
            chef.cooking();
        }
    }

}
複製代碼

經過構造方法傳入依賴的抽象對象。

Waiter waiter1 = new Waiter(sichuanChef);
waiter1.cooking();
Waiter waiter2 = new Waiter(shandongChef);
waiter2.cooking();
複製代碼

運行看一下結果。

四川廚師作飯
山東廚師作飯
複製代碼

首次建立的時候就肯定了依賴,既是優勢又是缺點。

優勢是避免了被修改。

缺點是更換依賴,就須要從新再建立對象了。

三、Setter方法傳遞依賴對象

package com.fanqiekt.principle.inversion;

/**
 * Setter方法傳遞依賴對象
 *
 * @author 番茄課堂-懶人
 */
public class Waiter implements IWaiter {

    private IChef chef;

    public void setChef(IChef chef){
        this.chef = chef;
    }

    @Override
    public void cooking(){
        if(chef!=null) {
            chef.cooking();
        }
    }

}
複製代碼

經過set方法賦值依賴對象。

Waiter plan = new Waiter();
plan.setChef(sichuanChef);
plan.cooking();
plan.setChef(shandongChef);
plan.cooking();
複製代碼

運行看一下結果。

四川廚師作飯
山東廚師作飯
複製代碼

Setter既能夠更換依賴對象,也不用每次調用方法時都傳入依賴對象。

三、優勢

咱們來總結一下依賴倒置原則的幾個優勢。

下降風險 依賴抽象,大大提升代碼的健壯性,風險天然而然就被下降了。

易維護易擴展 依賴抽象,纔會有框架,基於框架,擴展會更方便,維護起來也更省事。

增長開發速度 定好抽象結構就能夠並行開發了,而不用過多的被他人的進度干預。

四、嘻哈說

接下來,請您欣賞依賴倒置原則的原創歌曲

嘻哈說:依賴倒置原則
做曲:懶人
做詞:懶人
Rapper:懶人

須要依賴廚師爲我作頓美食
不用管他到底川系或者徽系
只依賴廚師接口作法多麼美麗
否則修改起來牽扯太多的話是多麼費事
set方法構造方法接口方法能夠將依賴作個配置
依賴倒置原則就是這麼回事
抽象不依賴細節 細節依賴抽象
高層不依賴低層 都應該依賴抽象
面向接口編程記住這點才能在代碼路走的夠長
易擴展易維護風險下降增長開發速度
就像番茄課堂同樣酷
複製代碼

試聽請點擊這裏

閒來無事聽聽曲,知識已填腦中去;

學習複習新方式,頭戴耳機不小覷。

番茄課堂,學習也要酷。

相關文章
相關標籤/搜索