设计模式:依赖倒置原则
依賴倒置原則定義
依賴倒置原則(Dependence Inversion Principle ,DIP)定義如下:
High level modules should not depend upon low level modules,Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstracts.
翻譯過來為:
高層模塊不應該依賴低層模塊,兩者都應該依賴抽象
抽象不應該依賴細節
細節應該依賴抽象
也可以說高層模塊,低層模塊,細節都應該依賴抽象
每一個邏輯的實現都是由顆粒原子邏輯組成的,顆粒原子邏輯就是低層模塊,而顆粒原子邏輯組成的模塊就是高層模塊。在java語言中,抽象就是接口或抽象類,兩都都是不能直接被實例化的,細節就是實現類,實現接口或繼承抽象類而產生的類就是細節,兩者都可以直接被實例化。
依賴倒置原則在java語言中,表現是:
模塊間的依賴通過抽象發生,實現類之間不發生直接的依賴關系,其依賴關系是通過接口或抽象類產生的。
接口或抽象類不依賴實現類
實現類依賴接口或抽象類
更加精簡的定義就是“面向接口編程”—OOD(Object-Oriented Design,面向對象設計)的精髓之一。
依賴倒置原則的好處
采用依賴倒置原則可以減少類間的耦合性,提高系統的穩定,降低并行開發引起的風險,提高代碼的可讀性和可維護性。
為什么我們要符合依賴倒置原則
我們通過一個例子說明依賴倒置原則對于開發有上面的好處。
大家都喜歡閱讀,閱讀文學經典滋潤自己的內心心靈,下面是小明同學閱讀文學經典的一個類圖:
小明閱讀文學數據類圖
文學經典的源代碼:
//文學經典類 public class LiteraryClassic{//閱讀文學經典public void read(){System.out.println("文學經典閱讀,滋潤自己的內心心靈");} }小明類:
//小明類 public class XiaoMing{//閱讀文學經典public void read(LiteraryClassic literaryClassic){literaryClassic.read();} }場景類:
public class Client{public static void main(Strings[] args){XiaoMing xiaoming = new XiaoMing();LiteraryClassic literaryClassic = new LiteraryClassic();//小明閱讀文學經典xiaoming.read(literaryClassic);}}看,我們的實現,小明同學可以閱讀文學經典了。
小明同學看了一段文學經典后,忽然他想看看看小說來放松一下自己,我們實現一個小說類:
小說類源代碼
//小說類 public class Novel{//閱讀小說public void read(){System.out.println("閱讀小說,放松自己");} }現在我們再來看代碼,發現XiaoMing類的read方法只與文學經典LiteraryClassic類是強依賴,緊耦合關系,小明同學竟然閱讀不了小說類。這與現實明顯的是不符合的,代碼設計的是有問題的。那么問題在那里呢?
我們看小明類,此類是一個高層模塊,并且是一個細節實現類,此類依賴的是一個文學經典LiteraryClassic類,而文學經典LiteraryClassic類也是一個細節實現類。這是不是就與我們說的依賴倒置原則相違背呢?依賴倒置原則是說我們的高層模塊,實現類,細節類都應該是依賴與抽象,依賴與接口和抽象類。
為了解決小明同學閱讀小說的問題,我們根據依賴倒置原則先抽象一個閱讀者接口,下面是完整的uml類圖:
讀者與閱讀動作解耦
IReader接口:
public interface IReader{//閱讀public void read(IRead read){read.read();}}再定義一個被閱讀的接口IRead:
public interface IRead{//被閱讀public void read(); }再定義文學經典類和小說類:
//文學經典類 public class LiteraryClassic implements IRead{//閱讀文學經典public void read(){System.out.println("文學經典閱讀,滋潤自己的內心心靈");} }小說類:
//小說類 public class Novel implements IRead{//閱讀小說public void read(){System.out.println("閱讀小說,放松自己");} }再實現小明類:
//小明類 public class XiaoMing implements IReader{//閱讀public void read(IRead read){read.read();} }然后,我們再讓小明分別閱讀文學經典和小說:
Client:
public class Client{public static void main(Strings[] args){XiaoMing xiaoming = new XiaoMing();IRead literaryClassic = new LiteraryClassic();//小明閱讀文學經典xiaoming.read(literaryClassic);IRead novel = new Novel();//小明閱讀小說xiaoming.read(novel);}}至此,小明同學是可以閱讀文學經典,又可以閱讀小說了,目的達到了。
為什么依賴抽象的接口可以適應變化的需求?這就要從接口的本質來說,接口就是把一些公司的方法和屬性聲明,然后具體的業務邏輯是可以在實現接口的具體類中實現的。所以我們當依賴對象是接口時,就可以適應所有的實現此接口的具體類變化。
依賴的三種方法
依賴是可以傳遞,A對象依賴B對象,B又依賴C,C又依賴D,……,依賴不止。只要做到抽象依賴,即使是多層的依賴傳遞也無所謂懼。
構造函數傳遞依賴對象
在類中通過構造函數聲明依賴對象,按照依賴注入的說法,這種方式叫做構造函數注入:
構造函數注入:
//小明類 public class XiaoMing implements IReader{private IRead read;//構造函數注入public XiaoMing(IRead read){this.read = read;}//閱讀public void read(){read.read();} }Setter方法傳遞依賴對象
在類中通過Setter方法聲明依賴關系,依照依賴注入的說法,這是Setter依賴注入:
//小明類 public class XiaoMing implements IReader{private IRead read;//Setter依賴注入public setRead(IRead read){this.read = read;}//閱讀public void read(){read.read();} }接口聲明依賴
在接口的方法中聲明依賴對象,在為什么我們要符合依賴倒置原則的例子中,我們采用了接口聲明依賴的方式,該方法也叫做接口注入。
依賴倒置原則的經驗
依賴倒置原則的本質就是通過抽象(接口或抽象類)使各個類或模塊的實現彼此獨立,不互相影響,實現模塊間的松耦合。我們在項目中使用這個原則要遵循下面的規則:
每個類盡量都有接口或者抽象類,或者抽象類和接口兩都具備
變量的表面類型盡量是接口或者抽象類
任何類都不應該從具體類派生
盡量不要覆寫基類的方法
結合里氏替換原則使用
里氏替換原則:父類出現的地方子類就能出現。結合本章我們得出了一個通俗的規則:接口負責定義public屬性和方法,并且聲明與其他對象的依賴關系。抽象類負責公共構造部分的實現,實現類準確的實現業務邏輯,同時在適當的時候對父類進行細化。
依賴倒置原則是6個設計原則中最難以實現的原則,它是實現開閉原則的重要方法,在項目中,大家只要記住是”面向接口編程”就基本上是抓住了依賴倒置原則的核心了。
總結
以上是生活随笔為你收集整理的设计模式:依赖倒置原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle 安装display,Lin
- 下一篇: python读取pdf翻译生成word