依賴倒置原則(DIP)

依賴倒置原則定義

依賴倒置原則(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.

翻譯過來為:

  • 高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴抽象
  • 抽象不應(yīng)該依賴細(xì)節(jié)
  • 細(xì)節(jié)應(yīng)該依賴抽象

也可以說高層模塊蹋订,低層模塊,細(xì)節(jié)都應(yīng)該依賴抽象

每一個(gè)邏輯的實(shí)現(xiàn)都是由顆粒原子邏輯組成的,顆粒原子邏輯就是低層模塊牛曹,而顆粒原子邏輯組成的模塊就是高層模塊刁憋。在java語言中采驻,抽象就是接口或抽象類,兩都都是不能直接被實(shí)例化的恕沫,細(xì)節(jié)就是實(shí)現(xiàn)類,實(shí)現(xiàn)接口或繼承抽象類而產(chǎn)生的類就是細(xì)節(jié)纱意,兩者都可以直接被實(shí)例化婶溯。

依賴倒置原則在java語言中,表現(xiàn)是:

  • 模塊間的依賴通過抽象發(fā)生偷霉,實(shí)現(xiàn)類之間不發(fā)生直接的依賴關(guān)系迄委,其依賴關(guān)系是通過接口或抽象類產(chǎn)生的。
  • 接口或抽象類不依賴實(shí)現(xiàn)類
  • 實(shí)現(xiàn)類依賴接口或抽象類

更加精簡(jiǎn)的定義就是“面向接口編程”—OOD(Object-Oriented Design类少,面向?qū)ο笤O(shè)計(jì))的精髓之一叙身。

依賴倒置原則的好處

采用依賴倒置原則可以減少類間的耦合性,提高系統(tǒng)的穩(wěn)定瞒滴,降低并行開發(fā)引起的風(fēng)險(xiǎn)曲梗,提高代碼的可讀性和可維護(hù)性。

為什么我們要符合依賴倒置原則

我們通過一個(gè)例子說明依賴倒置原則對(duì)于開發(fā)有上面的好處妓忍。

大家都喜歡閱讀虏两,閱讀文學(xué)經(jīng)典滋潤(rùn)自己的內(nèi)心心靈,下面是小明同學(xué)閱讀文學(xué)經(jīng)典的一個(gè)類圖:

小明閱讀文學(xué)數(shù)據(jù)類圖

文學(xué)經(jīng)典的源代碼:

//文學(xué)經(jīng)典類
public class LiteraryClassic{
    //閱讀文學(xué)經(jīng)典
    public void read(){
       System.out.println("文學(xué)經(jīng)典閱讀世剖,滋潤(rùn)自己的內(nèi)心心靈");
    }
}

小明類:

//小明類
public class XiaoMing{
    //閱讀文學(xué)經(jīng)典
    public void read(LiteraryClassic literaryClassic){
        literaryClassic.read();
    }
}

場(chǎng)景類:

public class Client{
   public static void main(Strings[] args){
      XiaoMing xiaoming = new XiaoMing();
      LiteraryClassic literaryClassic = new LiteraryClassic();
      //小明閱讀文學(xué)經(jīng)典
      xiaoming.read(literaryClassic);
   }

}

看定罢,我們的實(shí)現(xiàn),小明同學(xué)可以閱讀文學(xué)經(jīng)典了旁瘫。

小明同學(xué)看了一段文學(xué)經(jīng)典后祖凫,忽然他想看看看小說來放松一下自己,我們實(shí)現(xiàn)一個(gè)小說類:

小說類源代碼

//小說類
public class Novel{
    //閱讀小說
    public void read(){
       System.out.println("閱讀小說,放松自己");
    }
}

現(xiàn)在我們?cè)賮砜创a酬凳,發(fā)現(xiàn)XiaoMing類的read方法只與文學(xué)經(jīng)典LiteraryClassic類是強(qiáng)依賴惠况,緊耦合關(guān)系,小明同學(xué)竟然閱讀不了小說類宁仔。這與現(xiàn)實(shí)明顯的是不符合的稠屠,代碼設(shè)計(jì)的是有問題的。那么問題在那里呢?

我們看小明類权埠,此類是一個(gè)高層模塊榨了,并且是一個(gè)細(xì)節(jié)實(shí)現(xiàn)類,此類依賴的是一個(gè)文學(xué)經(jīng)典LiteraryClassic類攘蔽,而文學(xué)經(jīng)典LiteraryClassic類也是一個(gè)細(xì)節(jié)實(shí)現(xiàn)類龙屉。這是不是就與我們說的依賴倒置原則相違背呢?依賴倒置原則是說我們的高層模塊满俗,實(shí)現(xiàn)類转捕,細(xì)節(jié)類都應(yīng)該是依賴與抽象,依賴與接口和抽象類漫雷。

為了解決小明同學(xué)閱讀小說的問題瓜富,我們根據(jù)依賴倒置原則先抽象一個(gè)閱讀者接口,下面是完整的uml類圖:

讀者與閱讀動(dòng)作解耦

IReader接口:

public interface IReader{
   //閱讀
   public void read(IRead read){
       read.read();
   }

}

再定義一個(gè)被閱讀的接口IRead:

public interface IRead{
   //被閱讀
   public void read();
}

再定義文學(xué)經(jīng)典類和小說類:
文學(xué)經(jīng)典類:

//文學(xué)經(jīng)典類
public class LiteraryClassic implements IRead{
    //閱讀文學(xué)經(jīng)典
    public void read(){
       System.out.println("文學(xué)經(jīng)典閱讀,滋潤(rùn)自己的內(nèi)心心靈");
    }
}

小說類:

//小說類
public class Novel implements IRead{
    //閱讀小說
    public void read(){
       System.out.println("閱讀小說降盹,放松自己");
    }
}

再實(shí)現(xiàn)小明類:

//小明類
public class XiaoMing implements IReader{
    //閱讀
    public void read(IRead read){
        read.read();
    }
}

然后与柑,我們?cè)僮屝∶鞣謩e閱讀文學(xué)經(jīng)典和小說:

Client:

public class Client{
   public static void main(Strings[] args){
      XiaoMing xiaoming = new XiaoMing();
      IRead literaryClassic = new LiteraryClassic();
      //小明閱讀文學(xué)經(jīng)典
      xiaoming.read(literaryClassic);

      IRead novel = new Novel();
      //小明閱讀小說
      xiaoming.read(novel);
   }

}

至此,小明同學(xué)是可以閱讀文學(xué)經(jīng)典蓄坏,又可以閱讀小說了价捧,目的達(dá)到了。

為什么依賴抽象的接口可以適應(yīng)變化的需求涡戳?這就要從接口的本質(zhì)來說结蟋,接口就是把一些公司的方法和屬性聲明,然后具體的業(yè)務(wù)邏輯是可以在實(shí)現(xiàn)接口的具體類中實(shí)現(xiàn)的渔彰。所以我們當(dāng)依賴對(duì)象是接口時(shí)嵌屎,就可以適應(yīng)所有的實(shí)現(xiàn)此接口的具體類變化。

依賴的三種方法

依賴是可以傳遞恍涂,A對(duì)象依賴B對(duì)象宝惰,B又依賴C,C又依賴D再沧,……尼夺,依賴不止。只要做到抽象依賴炒瘸,即使是多層的依賴傳遞也無所謂懼淤堵。
對(duì)象的依賴關(guān)系有三種方式來傳遞:

構(gòu)造函數(shù)傳遞依賴對(duì)象

在類中通過構(gòu)造函數(shù)聲明依賴對(duì)象,按照依賴注入的說法顷扩,這種方式叫做構(gòu)造函數(shù)注入:

構(gòu)造函數(shù)注入:

//小明類
public class XiaoMing implements IReader{
     private IRead read;
     //構(gòu)造函數(shù)注入
     public XiaoMing(IRead read){
        this.read = read;
     }

    //閱讀
    public void read(){
        read.read();
    }
}

Setter方法傳遞依賴對(duì)象

在類中通過Setter方法聲明依賴關(guān)系拐邪,依照依賴注入的說法,這是Setter依賴注入:

//小明類
public class XiaoMing implements IReader{
     private IRead read;
     //Setter依賴注入
     public setRead(IRead read){
        this.read = read;
     }

    //閱讀
    public void read(){
        read.read();
    }
}

接口聲明依賴

在接口的方法中聲明依賴對(duì)象隘截,在為什么我們要符合依賴倒置原則的例子中扎阶,我們采用了接口聲明依賴的方式事富,該方法也叫做接口注入。

依賴倒置原則的經(jīng)驗(yàn)

依賴倒置原則的本質(zhì)就是通過抽象(接口或抽象類)使各個(gè)類或模塊的實(shí)現(xiàn)彼此獨(dú)立乘陪,不互相影響,實(shí)現(xiàn)模塊間的松耦合雕擂。我們?cè)陧?xiàng)目中使用這個(gè)原則要遵循下面的規(guī)則:

  • 每個(gè)類盡量都有接口或者抽象類啡邑,或者抽象類和接口兩都具備
  • 變量的表面類型盡量是接口或者抽象類
  • 任何類都不應(yīng)該從具體類派生
  • 盡量不要覆寫基類的方法
    如果基類是一個(gè)抽象類,而這個(gè)方法已經(jīng)實(shí)現(xiàn)了井赌,子類盡量不要覆寫谤逼。類間依賴的是抽象,覆寫了抽象方法仇穗,對(duì)依賴的穩(wěn)定性會(huì)有一定的影響流部。
  • 結(jié)合里氏替換原則使用

里氏替換原則:父類出現(xiàn)的地方子類就能出現(xiàn)。結(jié)合本章我們得出了一個(gè)通俗的規(guī)則:接口負(fù)責(zé)定義public屬性和方法纹坐,并且聲明與其他對(duì)象的依賴關(guān)系枝冀。抽象類負(fù)責(zé)公共構(gòu)造部分的實(shí)現(xiàn),實(shí)現(xiàn)類準(zhǔn)確的實(shí)現(xiàn)業(yè)務(wù)邏輯耘子,同時(shí)在適當(dāng)?shù)臅r(shí)候?qū)Ω割愡M(jìn)行細(xì)化果漾。

依賴倒置原則是6個(gè)設(shè)計(jì)原則中最難以實(shí)現(xiàn)的原則,它是實(shí)現(xiàn)開閉原則的重要方法谷誓,在項(xiàng)目中绒障,大家只要記住是”面向接口編程”就基本上是抓住了依賴倒置原則的核心了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捍歪,一起剝皮案震驚了整個(gè)濱河市户辱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌糙臼,老刑警劉巖庐镐,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弓摘,居然都是意外死亡焚鹊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門韧献,熙熙樓的掌柜王于貴愁眉苦臉地迎上來末患,“玉大人,你說我怎么就攤上這事锤窑¤嫡耄” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵渊啰,是天一觀的道長(zhǎng)探橱。 經(jīng)常有香客問我申屹,道長(zhǎng),這世上最難降的妖魔是什么隧膏? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任哗讥,我火速辦了婚禮,結(jié)果婚禮上胞枕,老公的妹妹穿的比我還像新娘杆煞。我一直安慰自己,他們只是感情好腐泻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布决乎。 她就那樣靜靜地躺著,像睡著了一般派桩。 火紅的嫁衣襯著肌膚如雪构诚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天铆惑,我揣著相機(jī)與錄音范嘱,去河邊找鬼。 笑死员魏,一個(gè)胖子當(dāng)著我的面吹牛彤侍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逆趋,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盏阶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了闻书?” 一聲冷哼從身側(cè)響起名斟,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎魄眉,沒想到半個(gè)月后砰盐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坑律,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年岩梳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晃择。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冀值,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宫屠,到底是詐尸還是另有隱情列疗,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布浪蹂,位于F島的核電站抵栈,受9級(jí)特大地震影響告材,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜古劲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一斥赋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧产艾,春花似錦灿渴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹬挤。三九已至缚窿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間焰扳,已是汗流浹背倦零。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吨悍,地道東北人扫茅。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像育瓜,于是被迫代替她去往敵國(guó)和親葫隙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容