高層模組不應該依賴低層模組,兩者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象。
簡單的說就是要求對抽象進行程式設計,不要對實現進行程式設計,這樣就降低了客戶與實現模組間的耦合。
下面看一個例子來理解依賴倒轉原則:組裝電腦
現要組裝一臺電腦,需要配件cpu,硬碟,記憶體條。只有這些配置都有了,計算機才能正常的執行。選擇cpu有很多選擇,如Intel,AMD等,硬碟可以選擇希捷,西數等,記憶體條可以選擇金士頓,海盜船等。
希捷硬碟類XiJieHardDisk)
package com.lmcode.principles.DependenceInversionPrinciple;
// 希捷硬碟
public class XiJieHardDisk {
public void save(String data) {
System.out.println("使用希捷硬碟儲存資料" + data);
}
public String get() {
System.out.println("使用希捷希捷硬碟取資料");
return "資料";
}
}
Intel處理器IntelCpu
package com.lmcode.principles.DependenceInversionPrinciple;
// Intel處理器
public class IntelCpu {
public void run() {
System.out.println("使用Intel處理器");
}
}
金士頓記憶體條KingstonMemory
package com.lmcode.principles.DependenceInversionPrinciple;
// 金士頓記憶體條
public class KingstonMemory {
public void save() {
System.out.println("使用金士頓作為記憶體條");
}
}
電腦Computer
package com.lmcode.principles.DependenceInversionPrinciple;
public class Computer {
private XiJieHardDisk hardDisk;
private IntelCpu cpu;
private KingstonMemory memory;
public IntelCpu getCpu() {return cpu;}
public void setCpu(IntelCpu cpu) {this.cpu = cpu;}
public KingstonMemory getMemory() {return memory;}
public void setMemory(KingstonMemory memory) {this.memory = memory;}
public XiJieHardDisk getHardDisk() {return hardDisk;}
public void setHardDisk(XiJieHardDisk hardDisk) {this.hardDisk = hardDisk;}
public void run() {
System.out.println("計算機工作");
cpu.run();
memory.save();
String data = hardDisk.get();
System.out.println("從硬碟中獲取的資料為:" + data);
}
}
測試類main用來組裝電腦。
package com.lmcode.principles.DependenceInversionPrinciple;
public class main {
public static void main(String[] args) {
// 建立元件物件
XiJieHardDisk xiJieHardDisk = new XiJieHardDisk();
IntelCpu intelCpu = new IntelCpu();
KingstonMemory kingstonMemory = new KingstonMemory();
// 建立電腦物件
Computer computer = new Computer();
// 組裝
computer.setCpu(intelCpu);
computer.setHardDisk(xiJieHardDisk);
computer.setMemory(kingstonMemory);
// 執行
computer.run();
}
}
上面程式碼可以看到已經組裝了一臺電腦,但是似乎組裝的電腦的cpu只能是Intel的,記憶體條只能是金士頓的,硬碟只能是希捷的,這對使用者肯定是不友好的,使用者有了機箱肯定是想按照自己的喜好,選擇自己喜歡的配件。
根據依賴倒轉原則進行改進:
程式碼我們只需要修改Computer類,讓Computer類依賴抽象(各個配件的介面),而不是依賴於各個元件具體的實現類。
物件導向的開發很好的解決了這個問題,一般情況下抽象的變化機率很小,讓使用者程式依賴於抽象,實現的細節也依賴於抽象。即使實現
細節不斷變動,只要抽象不變,客戶程式就不需要變化。這大大降低了客戶程式與實現細節的耦合度。
cpu介面,硬碟介面,記憶體條介面
package com.lmcode.principles.DependenceInversionPrinciplePro;
//cpu介面
public interface Cpu {
// 執行cpu
public void run();
}
package com.lmcode.principles.DependenceInversionPrinciplePro;
// 硬碟介面
public interface HardDisk {
// 儲存資料
public void save(String data);
// 獲取資料
public String get();
}
package com.lmcode.principles.DependenceInversionPrinciplePro;
//記憶體條介面
public interface Memory {
public void save();
}
實現類
package com.lmcode.principles.DependenceInversionPrinciplePro;
// Intel處理器
public class IntelCpu implements Cpu{
public void run() {
System.out.println("使用Intel處理器");
}
}
package com.lmcode.principles.DependenceInversionPrinciplePro;
// 金士頓記憶體條
public class KingstonMemory implements Memory{
public void save() {
System.out.println("使用金士頓作為記憶體條");
}
}
package com.lmcode.principles.DependenceInversionPrinciplePro;
// 希捷硬碟
public class XiJieHardDisk implements HardDisk{
public void save(String data) {
System.out.println("使用希捷硬碟儲存資料" + data);
}
public String get() {
System.out.println("使用希捷硬碟取資料");
return "資料";
}
}
Computer
此時宣告元件不能宣告具體的實現類,而是父介面型別的抽象
package com.lmcode.principles.DependenceInversionPrinciplePro;
public class Computer {
// 宣告元件不能宣告具體的實現類,而是父介面型別的抽象
private HardDisk hardDisk;
private Cpu cpu;
private Memory memory;
public HardDisk getHardDisk() {
return hardDisk;
}
public void setHardDisk(HardDisk hardDisk) {
this.hardDisk = hardDisk;
}
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
public Memory getMemory() {
return memory;
}
public void setMemory(Memory memory) {
this.memory = memory;
}
public void run() {
System.out.println("計算機工作");
cpu.run();
memory.save();
String data = hardDisk.get();
System.out.println("從硬碟中獲取的資料為:" + data);
}
}
main
package com.lmcode.principles.DependenceInversionPrinciplePro;
public class main {
public static void main(String[] args) {
// 建立元件物件
HardDisk hardDisk = new XiJieHardDisk();
Cpu cpu = new IntelCpu();
Memory memory = new KingstonMemory();
// 建立電腦物件
Computer computer = new Computer();
// 組裝
computer.setCpu(cpu);
computer.setHardDisk(hardDisk);
computer.setMemory(memory);
// 執行
computer.run();
}
}
此時加入需要換cpu,只需要建立一個cpu的類,實現cpu介面,然後再main中建立新的cpu然後作為引數傳遞