設計模式七大原則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、繼承時遵循里氏替換原則