依賴倒置原則(Dependence Inversion Principle,DIP)的原始定義爲:高層模塊不該該依賴低層模塊,二者都應該依賴其抽象;抽象不該該依賴細節,細節應該依賴抽象。其核心思想是:要面向接口編程,不要面向實現編程。html
依賴倒置原則的目的是經過要面向接口的編程來下降類間的耦合性,因此咱們在實際編程中只要遵循如下4點,就能在項目中知足這個規則。編程
1.每一個類儘可能提供接口或抽象類,或者二者都具有。ide
2.變量的聲明類型儘可能是接口或者是抽象類。函數
3.任何類都不該該從具體類派生。this
4.使用繼承時儘可能遵循里氏替換原則。spa
下面給出一個具體的例子進行說明。3d
UML類圖:code
有三種方式能夠實現依賴倒置:htm
方式1:使用接口傳遞,QQPlayer實現了IPlayerA,而IPlayerA依賴於IFile,這樣經過IPlayerA將IFile傳遞給了QQPlayer類的對象。對象
方式2:使用構造函數,NEPlayer實現了IPlayerB,而且NEPlayer關聯IFile (實線箭頭),經過構造函數將IFile的實例傳遞給NEPlayer類的對象。
方式3:使用屬性Setter方法,KWPlayer實現了IPlayerB,而且KWPlayer關聯IFile (實現箭頭),經過私有變量的Setter方法setFile(),將IFile實例傳遞給KWPlayer類的對象。
下面是根據UML類圖實現的Java代碼:
1 public interface IFile { 2 public String getFileName(); 3 } 4 5 public class MusicFile implements IFile { 6 7 private String fileName; 8 9 public MusicFile(String fileName) { 10 this.fileName = fileName; 11 } 12 13 @Override 14 public String getFileName() { 15 return this.fileName; 16 } 17 18 } 19 20 public interface IPlayerA { 21 public void playFile(IFile file); 22 } 23 24 public interface IPlayerB { 25 public void play(); 26 } 27 28 public class QQPlayer implements IPlayerA { 29 @Override 30 public void playFile(IFile file) { 31 String fileName = file.getFileName(); 32 System.out.println("QQ音樂開始播放歌曲:" + fileName); 33 } 34 } 35 36 public class NEPlayer implements IPlayerB { 37 private IFile file; 38 39 public NEPlayer(IFile file) { 40 this.file = file; 41 } 42 43 @Override 44 public void play() { 45 String fileName = this.file.getFileName(); 46 System.out.println("網易音樂開始播放歌曲:" + fileName); 47 } 48 } 49 50 public class KWPlayer implements IPlayerB { 51 52 private IFile file; 53 54 public void setFile(IFile file) { 55 this.file = file; 56 } 57 58 @Override 59 public void play() { 60 // TODO Auto-generated method stub 61 String fileName = this.file.getFileName(); 62 System.out.println("酷我音樂開始播放歌曲:" + fileName); 63 } 64 } 65 66 public class Client { 67 public static void main(String[] args) { 68 byInterface(); 69 byConstruct(); 70 bySetter(); 71 } 72 73 // 方式1:接口方式 74 public static void byInterface() { 75 IFile file = new MusicFile("盜將行"); 76 QQPlayer player = new QQPlayer(); 77 player.playFile(file); 78 } 79 80 // 方式2:構造函數方式 81 public static void byConstruct() { 82 IFile file = new MusicFile("出山"); 83 NEPlayer player = new NEPlayer(file); 84 player.play(); 85 } 86 87 // 方式3:屬性Setter方式 88 public static void bySetter() { 89 IFile file = new MusicFile("芒種"); 90 KWPlayer player = new KWPlayer(); 91 player.setFile(file); 92 player.play(); 93 } 94 }