依賴倒置原則(DIP)

基本介紹

  1. 高層模塊不應(yīng)該直接依賴底層模塊,應(yīng)該依賴其抽象。
  2. 細節(jié)應(yīng)該依賴抽象,抽象不應(yīng)該依賴細節(jié)。
  3. 依賴倒置的中心思想是面向接口編程。
  4. 相對于細節(jié)的多變性,抽象的東西更穩(wěn)定,以抽象為基礎(chǔ)搭建的架構(gòu)比以細節(jié)為基礎(chǔ)的架構(gòu)要穩(wěn)定的多。
  5. 使用接口或抽象類的目的是制定好規(guī)范,而不涉及任何具體的操作,把展現(xiàn)細節(jié)的任務(wù)交給他們的實現(xiàn)類去完成。

代碼示例

示例一(錯誤寫法)

public class DependenceInversion {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new Email());
    }
}

// 電子郵件細節(jié)類
class Email {
    public String getInfo() {
        return "電子郵件信息為:Hello,World!";
    }
}

// 模擬人接收消息
class Person {
    public void receive(Email email) {
        System.out.println(email.getInfo());
    }
}

這是最簡單最容易想到的寫法,如果需要接收微信或者其它消息,則需要在person類新增接收的方法。所以可通過依賴倒置的方式解決,添加IReceiver接口做為緩沖層。

示例二(依賴倒置)

public class DependecyInversion {

    public static void main(String[] args) {
        //客戶端無需改變
        Person person = new Person();
        person.receive(new Email());
        person.receive(new WeChat());
    }
}

// 定義接口
interface IReceiver {
    String getInfo();
}

class Email implements IReceiver {
    @Override
    public String getInfo() {
        return "電子郵件信息: hello, world!";
    }
}

// 增加微信
class WeChat implements IReceiver {
    @Override
    public String getInfo() {
        return "微信信息: hello, world!";
    }
}

// 方式2
class Person {
    // 這里我們是對接口的依賴
    public void receive(IReceiver receiver) {
        System.out.println(receiver.getInfo());
    }
}

引入抽象的接口IReceiver,Person類只與接口發(fā)生依賴關(guān)系,在調(diào)用的時候只需要傳入接口的實現(xiàn)類即可。

傳遞方式

1.接口傳遞
public class DependencyPass {

    public static void main(String[] args) {
        ChangHong changHong = new ChangHong();
        OpenAndClose openAndClose = new OpenAndClose();
        // 通過接口的實現(xiàn)類實現(xiàn)
        openAndClose.open(changHong);
    }

}

// 開關(guān)的接口
interface IOpenAndClose {
    // 抽象方法,接收接口
    void open(ITV tv); 
}

// ITV接口
interface ITV {
    void play();
}

class ChangHong implements ITV {
    @Override
    public void play() {
        System.out.println("長虹電視機,打開");
    }
}

// 實現(xiàn)接口
class OpenAndClose implements IOpenAndClose {
    @Override
    public void open(ITV tv) {
        tv.play();
    }
}
2.構(gòu)造方法傳遞
public class DependencyPass {

    public static void main(String[] args) {
        ChangHong changHong = new ChangHong();
        // 通過構(gòu)造器進行依賴傳遞
        OpenAndClose openAndClose = new OpenAndClose(changHong);
        openAndClose.open();
    }

}

class ChangHong implements ITV {
    @Override
    public void play() {
        System.out.println("長虹電視機,打開");
    }
}


interface IOpenAndClose {
    void open(); //抽象方法
}

// ITV接口
interface ITV { 
    void play();
}

class OpenAndClose implements IOpenAndClose {
    public ITV tv; // 成員

    public OpenAndClose(ITV tv) { // 構(gòu)造器
        this.tv = tv;
    }

    @Override
    public void open() {
        this.tv.play();
    }
}
3.setter方法傳遞
public class DependencyPass {

    public static void main(String[] args) {
        ChangHong changHong = new ChangHong();

        //通過setter方法進行依賴傳遞
        OpenAndClose openAndClose = new OpenAndClose();
        openAndClose.setTv(changHong);
        openAndClose.open();
    }
}

interface IOpenAndClose {
    void open(); // 抽象方法

    void setTv(ITV tv);
}

interface ITV { // ITV接口
    void play();
}

class OpenAndClose implements IOpenAndClose {
    private ITV tv;

    @Override
    public void setTv(ITV tv) {
        this.tv = tv;
    }

    @Override
    public void open() {
        this.tv.play();
    }
}

class ChangHong implements ITV {

    @Override
    public void play() {
        System.out.println("長虹電視機,打開");
    }

}

總結(jié)

  1. 底層模塊盡量都要有抽象類或接口,或者兩者都有,程序穩(wěn)定性更好。
  2. 變量的聲明類型盡量是抽象類或接口,這樣我們的變量引用和實際對象間就存在一個緩沖層,利于程序擴展和優(yōu)化。
  3. 繼承時遵循里氏替換原則。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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