java設(shè)計模式六大原則——依賴倒置原則(面向接口編程)

定義:高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象罕拂;抽象不應(yīng)該依賴細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴抽象全陨。

問題由來:類A直接依賴類B爆班,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達(dá)成辱姨。這種場景下柿菩,類A一般是高層模塊,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯雨涛;類B和類C是低層模塊枢舶,負(fù)責(zé)基本的原子操作;假如修改類A替久,會給程序帶來不必要的風(fēng)險凉泄。

解決方案:將類A修改為依賴接口I,類B和類C各自實現(xiàn)接口I蚯根,類A通過接口I間接與類B或者類C發(fā)生聯(lián)系后众,則會大大降低修改類A的幾率。

依賴倒置原則基于這樣一個事實:相對于細(xì)節(jié)的多變性颅拦,抽象的東西要穩(wěn)定的多蒂誉。以抽象為基礎(chǔ)搭建起來的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)搭建起來的架構(gòu)要穩(wěn)定的多。在java中距帅,抽象指的是接口或者抽象類右锨,細(xì)節(jié)就是具體的實現(xiàn)類,使用接口或者抽象類的目的是制定好規(guī)范和契約碌秸,而不去涉及任何具體的操作陡蝇,把展現(xiàn)細(xì)節(jié)的任務(wù)交給他們的實現(xiàn)類去完成痊臭。

依賴倒置原則的核心思想是面向接口編程,我們依舊用一個例子來說明面向接口編程比相對于面向?qū)崿F(xiàn)編程好在什么地方登夫。場景是這樣的广匙,母親給孩子講故事,只要給她一本書恼策,她就可以照著書給孩子講故事了鸦致。代碼如下:

class Book{
    public String getContent(){
        return "很久很久以前有一個阿拉伯的故事……";
    }
}

class Mother{
    public void narrate(Book book){
        System.out.println("媽媽開始講故事");
        System.out.println(book.getContent());
    }
}

public class Client{
    public static void main(String[] args){
        Mother mother = new Mother();
        mother.narrate(new Book());
    }
}

運(yùn)行結(jié)果:
媽媽開始講故事
很久很久以前有一個阿拉伯的故事……

運(yùn)行良好,假如有一天涣楷,需求變成這樣:不是給書而是給一份報紙分唾,讓這位母親講一下報紙上的故事,報紙的代碼如下:

class Newspaper{
    public String getContent(){
        return "林書豪38+7領(lǐng)導(dǎo)尼克斯擊敗湖人……";
    }
} 

這位母親卻辦不到狮斗,因為她居然不會讀報紙上的故事绽乔,這太荒唐了,只是將書換成報紙碳褒,居然必須要修改Mother才能讀折砸。假如以后需求換成雜志呢?換成網(wǎng)頁呢沙峻?還要不斷地修改Mother睦授,這顯然不是好的設(shè)計。原因就是Mother與Book之間的耦合性太高了摔寨,必須降低他們之間的耦合度才行去枷。

我們引入一個抽象的接口IReader。讀物是复,只要是帶字的都屬于讀物:

interface IReader{
    public String getContent();
} 

Mother類與接口IReader發(fā)生依賴關(guān)系删顶,而Book和Newspaper都屬于讀物的范疇,他們各自都去實現(xiàn)IReader接口淑廊,這樣就符合依賴倒置原則了翼闹,代碼修改為:

class Newspaper implements IReader {
    public String getContent(){
        return "林書豪17+9助尼克斯擊敗老鷹……";
    }
}
class Book implements IReader{
    public String getContent(){
        return "很久很久以前有一個阿拉伯的故事……";
    }
}

class Mother{
    public void narrate(IReader reader){
        System.out.println("媽媽開始講故事");
        System.out.println(reader.getContent());
    }
}

public class Client{
    public static void main(String[] args){
        Mother mother = new Mother();
        mother.narrate(new Book());
        mother.narrate(new Newspaper());
    }
}

運(yùn)行結(jié)果:
媽媽開始講故事
很久很久以前有一個阿拉伯的故事……
媽媽開始講故事
林書豪17+9助尼克斯擊敗老鷹……

這樣修改后,無論以后怎樣擴(kuò)展Client類蒋纬,都不需要再修改Mother類了。這只是一個簡單的例子坚弱,實際情況中蜀备,代表高層模塊的Mother類將負(fù)責(zé)完成主要的業(yè)務(wù)邏輯,一旦需要對它進(jìn)行修改荒叶,引入錯誤的風(fēng)險極大碾阁。所以遵循依賴倒置原則可以降低類之間的耦合性,提高系統(tǒng)的穩(wěn)定性些楣,降低修改程序造成的風(fēng)險脂凶。

采用依賴倒置原則給多人并行開發(fā)帶來了極大的便利宪睹,比如上例中,原本Mother類與Book類直接耦合時蚕钦,Mother類必須等Book類編碼完成后才可以進(jìn)行編碼亭病,因為Mother類依賴于Book類。修改后的程序則可以同時開工嘶居,互不影響罪帖,因為Mother與Book類一點(diǎn)關(guān)系也沒有。參與協(xié)作開發(fā)的人越多邮屁、項目越龐大整袁,采用依賴導(dǎo)致原則的意義就越重大。現(xiàn)在很流行的TDD開發(fā)模式就是依賴倒置原則最成功的應(yīng)用佑吝。

傳遞依賴關(guān)系有三種方式坐昙,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構(gòu)造方法傳遞和setter方法傳遞芋忿,相信用過Spring框架的炸客,對依賴的傳遞方式一定不會陌生。

在實際編程中盗飒,我們一般需要做到如下3點(diǎn):

  • 低層模塊盡量都要有抽象類或接口嚷量,或者兩者都有。
  • 變量的聲明類型盡量是抽象類或接口逆趣。
  • 使用繼承時遵循里氏替換原則蝶溶。

依賴倒置原則的核心就是要我們面向接口編程,理解了面向接口編程宣渗,也就理解了依賴倒置抖所。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市痕囱,隨后出現(xiàn)的幾起案子田轧,更是在濱河造成了極大的恐慌,老刑警劉巖鞍恢,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件傻粘,死亡現(xiàn)場離奇詭異,居然都是意外死亡帮掉,警方通過查閱死者的電腦和手機(jī)弦悉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蟆炊,“玉大人稽莉,你說我怎么就攤上這事∩辏” “怎么了污秆?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵劈猪,是天一觀的道長。 經(jīng)常有香客問我良拼,道長战得,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任将饺,我火速辦了婚禮贡避,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘予弧。我一直安慰自己刮吧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布掖蛤。 她就那樣靜靜地躺著杀捻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚓庭。 梳的紋絲不亂的頭發(fā)上致讥,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機(jī)與錄音器赞,去河邊找鬼垢袱。 笑死,一個胖子當(dāng)著我的面吹牛港柜,可吹牛的內(nèi)容都是我干的请契。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼夏醉,長吁一口氣:“原來是場噩夢啊……” “哼爽锥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起畔柔,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤氯夷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后靶擦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腮考,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年玄捕,在試婚紗的時候發(fā)現(xiàn)自己被綠了踩蔚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡桩盲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出席吴,到底是詐尸還是另有隱情赌结,我是刑警寧澤捞蛋,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站柬姚,受9級特大地震影響拟杉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜量承,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一搬设、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撕捍,春花似錦拿穴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狮腿,卻和暖如春腿宰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缘厢。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工吃度, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贴硫。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓椿每,卻偏偏與公主長得像,于是被迫代替她去往敵國和親夜畴。 傳聞我的和親對象是個殘疾皇子拖刃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

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