1. 程式人生 > 實用技巧 >設計模式七大原則03---依賴倒轉原則

設計模式七大原則03---依賴倒轉原則

一、依賴倒轉原則(Dependence Inversion Principle)特點

1、依賴倒轉原則是基於這樣的設計理念:相對於細節的多變性,抽象的東西要穩定的多.以抽象為基礎搭建的架構比以細節為基礎的架構要穩定的多.在java中,抽象指的是介面或抽象類,細節就是具體的實現類

2、高層模組不應該依賴低層模組,二者都應該依賴其抽象

3、抽象不應該依賴細節,細節應該依賴抽象

4、使用介面或抽象類的目的是制定好規範,而不涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成

5、依賴倒轉(倒置)的中心思想是面向介面程式設計

二、案例演示

完成 Person 接收訊息的功能

方式一、普通實現

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

class Person{
    public void receiveMessage(Email email){
        email.receive();
    }
}

class Email {
    public void receive(){
        System.out.println("接收 email 資訊");
    }
}

上面的程式碼已經完成了我們的需求,但是存在一個問題,我們 Person 類裡面的 receiveMessage(Email email) 方法引數型別是 Email 型別的,它代表的意思是隻能接收 Email 型別的訊息,如果我這個時候想接收微信訊息、QQ 訊息,那麼就要繼續重寫 receiveMessage() 方法,這樣就比較麻煩.所以我們需要使用依賴倒置來改進

方式二、依賴倒置

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Person person = new Person();
        person.receiveMessage(new Email());
        person.receiveMessage(new Wechat());
        person.receiveMessage(new QQ());
    }
}

interface Message {
    public abstract void receive();
}

class Person {
    public void receiveMessage(Message message) {
        message.receive();
    }
}

class Email implements Message {
    public void receive() {
        System.out.println("接收 email 資訊");
    }
}

class Wechat implements Message {
    public void receive() {
        System.out.println("接收 wechat 資訊");
    }
}

class QQ implements Message {
    public void receive() {
        System.out.println("接收 qq 資訊");
    }
}

使用依賴倒置改進之後,擴充套件起來也比較方便了.

三、依賴關係傳遞的三種方式

依賴是可以傳遞的,A物件依賴B物件,B物件又依賴C物件,C物件又依賴D物件......生生不息,依賴不止.要記住一點:只要做到抽象依賴,即使多層的依賴傳遞也無所畏懼.物件的依賴關係主要有三種方式來傳遞.

1、介面傳遞

在介面的方法中宣告依賴物件,該方法也叫做介面注入.

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Idriver idriver = new Driver();
        idriver.drive(new Benz());
        idriver.drive(new Porsche());
    }
}

interface Icar {
    public void run();
}

interface Idriver {
    public void drive(Icar icar);
}

class Benz implements Icar {
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

class Porsche implements Icar {
    @Override
    public void run() {
        System.out.println("Porsche run...");
    }
}

class Driver implements Idriver {
    @Override
    public void drive(Icar icar) {
        icar.run();
    }
}

2、構造方法傳遞

在類中通過建構函式依賴物件,安裝依賴注入的說法,這種方式叫做建構函式注入.

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Idriver benz = new Driver(new Benz());
        benz.drive();
        Idriver porsche = new Driver(new Porsche());
        porsche.drive();
    }
}

interface Icar {
    public void run();
}

interface Idriver {
    public void drive();
}

class Benz implements Icar {
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

class Porsche implements Icar {
    @Override
    public void run() {
        System.out.println("Porsche run...");
    }
}

class Driver implements Idriver {
    private Icar icar;

    public Driver(Icar icar){
        this.icar = icar;
    }

    @Override
    public void drive() {
        icar.run();
    }
}

3、setter 方法傳遞

在抽象中設定 setter 方法宣告依賴關係,依照依賴注入的說法.這個是 setter 依賴注入

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Driver benzDriver = new Driver();
        benzDriver.setIcar(new Benz());
        benzDriver.drive();

        Driver PorsDriver = new Driver();
        PorsDriver.setIcar(new Porsche());
        PorsDriver.drive();
    }
}

interface Icar {
    public void run();
}

interface Idriver {
    public void drive();
}

class Benz implements Icar {
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

class Porsche implements Icar {
    @Override
    public void run() {
        System.out.println("Porsche run...");
    }
}

class Driver implements Idriver {
    private Icar icar;

    public void setIcar(Icar icar) {
        this.icar = icar;
    }

    @Override
    public void drive() {
        icar.run();
    }
}

  

四、依賴倒置注意事項

1、低層模組儘量都要有抽象類或介面,或者兩者都有,程式穩定性更好

2、變數的宣告型別儘量是抽象類或介面,,這樣我們的變數引用和實際物件間,就存在一個緩衝層,利於程式擴充套件和優化

3、繼承時遵循里氏替換原則