什麼是依賴倒轉原則
依賴倒轉(Dependence Inversion Principle ):是程序要依賴於抽象接口,不要依賴於具體實現。簡單的說就是要求對抽象進行編程,不要對實現進行編程,這樣就下降了客戶與實現模塊間的耦合。html
1.抽象不該該依賴於細節,細節應該依賴於抽象。編程
2.高層模塊不依賴底層模塊,二者都依賴抽象。 框架
咱們舉個例子:電腦有不一樣的組件,硬盤,內存,主板。this
硬盤抽象類url
1 //硬盤抽象類 2 public abstract class HardDisk { 3 public abstract void doSomething(); 4 }
具體硬盤(希捷硬盤)spa
1 //希捷硬盤 2 public class XiJieHardDisk extends HardDisk { 3 4 public void doSomething() { 5 System.out.println("希捷硬盤"); 6 } 7 8 }
具體硬盤(西數硬盤).net
1 public class XiShuHardDisk extends HardDisk { 2 3 public void doSomething() { 4 System.out.println("西數硬盤"); 5 } 6 7 }
主板抽象類 設計
1 //主板抽象類 2 public abstract class MainBoard { 3 public abstract void doSomething(); 4 }
具體主板(華碩主板)3d
1 public class HuaShuoMainBoard extends MainBoard{ 2 3 public void doSomething() { 4 System.out.println("華碩主板"); 5 } 6 7 }
具體主板(微星主板)code
1 public class WeiXingMainBoard extends MainBoard { 2 3 public void doSomething() { 4 System.out.println("微星主板"); 5 } 6 7 }
內存抽象類
1 //內存抽象類 2 public abstract class Memory { 3 public abstract void doSomething(); 4 }
具體內存(金士頓內存)
1 public class JinShiDunMemory extends Memory { 2 3 public void doSomething() { 4 System.out.println("金士頓內存"); 5 } 6 7 }
具體內存(三星內存)
1 public class SanxingMemory extends Memory { 2 3 public void doSomething() { 4 System.out.println("三星內存"); 5 } 6 7 }
如今,電腦的各個零部件都有了,只差電腦了。首先,咱們不按照依賴倒轉原則,按照傳統模式
傳統的過程式設計傾向於使高層次的模塊依賴於低層次的模塊,抽象層依賴於具體的層次。
這樣,電腦應該是這樣的
1 //電腦 2 public class Computer{ 3 private HuaShuoMainBoard huaShuoMainBoard; 4 private JinShiDunMemory jinShiDunMemory; 5 private XiJieHardDisk xiJieHardDisk; 6 7 public HuaShuoMainBoard getHuaShuoMainBoard() { 8 return huaShuoMainBoard; 9 } 10 public void setHuaShuoMainBoard(HuaShuoMainBoard huaShuoMainBoard) { 11 this.huaShuoMainBoard = huaShuoMainBoard; 12 } 13 public JinShiDunMemory getJinShiDunMemory() { 14 return jinShiDunMemory; 15 } 16 public void setJinShiDunMemory(JinShiDunMemory jinShiDunMemory) { 17 this.jinShiDunMemory = jinShiDunMemory; 18 } 19 public XiJieHardDisk getXiJieHardDisk() { 20 return xiJieHardDisk; 21 } 22 public void setXiJieHardDisk(XiJieHardDisk xiJieHardDisk) { 23 this.xiJieHardDisk = xiJieHardDisk; 24 } 25 }
這時,要組裝一臺電腦
public class MainClass { public static void main(String[] args) { Computer computer = new Computer(); computer.setHuaShuoMainBoard(new HuaSuoMainBoard()); computer.setJinShiDunMemory(new JinShiDunMemory()); computer.setXiJieHardDisk(new XiJieHardDisk()); computer.setHuaShuoMainBoard(new WeiXingMainBoard());//報錯,沒法安裝 } }
能夠看到,這種狀況下,這臺電腦就只能安裝華碩主板,金士頓內存和希捷硬盤了,這對用戶確定是不友好的,用戶有了機箱確定是想按照本身的喜愛,選擇本身喜歡的配件。
電腦就是高層業務邏輯,主板,內存,硬盤就是中層模塊,還有更低的底層模塊咱們沒有寫那麼細,但都是一個意思,這樣的方式顯然是不可取的。
下面,咱們改造一下,讓Computer依賴接口或抽象類,下面的模塊一樣如此
Computer
1 public class Computer { 2 private MainBoard mainBoard; 3 private Memory memory; 4 private HardDisk harddisk; 5 6 public MainBoard getMainBoard() { 7 return mainBoard; 8 } 9 10 public void setMainBoard(MainBoard mainBoard) { 11 this.mainBoard = mainBoard; 12 } 13 14 public Memory getMemory() { 15 return memory; 16 } 17 18 public void setMemory(Memory memory) { 19 this.memory = memory; 20 } 21 22 public HardDisk getHarddisk() { 23 return harddisk; 24 } 25 26 public void setHarddisk(HardDisk harddisk) { 27 this.harddisk = harddisk; 28 } 29 }
這時,再組裝
1 public class MainClass { 2 public static void main(String[] args) { 3 Computer computer = new Computer(); 4 computer.setMainBoard(new HuaSuoMainBoard()); 5 computer.setMemory(new JinShiDunMemory()); 6 computer.setHarddisk(new XiJieHardDisk()); 7 8 computer.setMainBoard(new WeiXingMainBoard());//徹底沒有問題 9 } 10 }
這樣,用戶就能夠根據本身的喜愛來選擇本身喜歡的品牌,組裝電腦了。
爲何要採起依賴倒轉這種方式
面向過程的開發,上層調用下層,上層依賴於下層,當下層劇烈變更時上層也要跟着變更,這就會致使模塊的複用性下降並且大大提升了開發的成本。
面向對象的開發很好的解決了這個問題,通常狀況下抽象的變化機率很小,讓用戶程序依賴於抽象,實現的細節也依賴於抽象。即便實現細節不斷變更,只要抽象不變,客戶程序就不須要變化。這大大下降了客戶程序與實現細節的耦合度。
依賴倒轉模式應用實例
1.工廠方法模式
2.模板方法模式
3.迭代模式
綜上所訴,咱們能夠看出一個應用中的重要策略決定及業務模型正是在這些高層的模塊中。也正是這些模型包含着應用的特性。可是,當這些模塊依賴於低層模塊時,低層模塊的修改將會直接影響到它們,迫使它們也去改變。這種境況是荒謬的。應該是處於高層的模塊去迫使那些低層的模塊發生改
變。應該是處於高層的模塊優先於低層的模塊。不管如何高層的模塊也不該依賴於低層的模塊。並且,咱們想可以複用的是高層的模塊。經過子程序庫的形式,咱們已經能夠很好地複用低層的模塊了。當高層的模塊依賴於低層的模塊時,這些高層模塊就很難在不一樣的環境中複用。可是,當那些高層模塊獨
立於低層模塊時,它們就能很簡單地被複用了。這正是位於框架設計的最核心之處的原則。