Java依賴(lài)倒轉(zhuǎn)原則_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
定義:高層模塊不應(yīng)該依賴(lài)低層模塊,二者都應(yīng)該依賴(lài)其抽象;抽象不應(yīng)該依賴(lài)細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴(lài)抽象。
問(wèn)題由來(lái):類(lèi)A直接依賴(lài)類(lèi)B,假如要將類(lèi)A改為依賴(lài)類(lèi)C,則必須通過(guò)修改類(lèi)A的代碼來(lái)達(dá)成。這種場(chǎng)景下,類(lèi)A一般是高層模塊,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯;類(lèi)B和類(lèi)C是低層模塊,負(fù)責(zé)基本的原子操作;假如修改類(lèi)A,會(huì)給程序帶來(lái)不必要的風(fēng)險(xiǎn)。
解決方案:將類(lèi)A修改為依賴(lài)接口I,類(lèi)B和類(lèi)C各自實(shí)現(xiàn)接口I,類(lèi)A通過(guò)接口I間接與類(lèi)B或者類(lèi)C發(fā)生聯(lián)系,則會(huì)大大降低修改類(lèi)A的幾率。
依賴(lài)倒置原則基于這樣一個(gè)事實(shí):相對(duì)于細(xì)節(jié)的多變性,抽象的東西要穩(wěn)定的多。以抽象為基礎(chǔ)搭建起來(lái)的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)搭建起來(lái)的架構(gòu)要穩(wěn)定的多。在Java中,抽象指的是接口或者抽象類(lèi),細(xì)節(jié)就是具體的實(shí)現(xiàn)類(lèi),使用接口或者抽象類(lèi)的目的是制定好規(guī)范和契約,而不去涉及任何具體的操作,把展現(xiàn)細(xì)節(jié)的任務(wù)交給他們的實(shí)現(xiàn)類(lèi)去完成。
依賴(lài)倒置原則的核心思想是面向接口編程,我們依舊用一個(gè)例子來(lái)說(shuō)明面向接口編程比相對(duì)于面向?qū)崿F(xiàn)編程好在什么地方。場(chǎng)景是這樣的,母親給孩子講故事,只要給她一本書(shū),她就可以照著書(shū)給孩子講故事了。代碼如下:
class Book{
public String getContent(){
return "很久很久以前有一個(gè)阿拉伯的故事……";
}
}
class Mother{
public void narrate(Book book){
System.out.println("媽媽開(kāi)始講故事");
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é)果:
媽媽開(kāi)始講故事
很久很久以前有一個(gè)阿拉伯的故事……
運(yùn)行良好,假如有一天,需求變成這樣:不是給書(shū)而是給一份報(bào)紙,讓這位母親講一下報(bào)紙上的故事,報(bào)紙的代碼如下:
class Newspaper{
public String getContent(){
return "林書(shū)豪38+7領(lǐng)導(dǎo)尼克斯擊敗湖人……";
}
}
這位母親卻辦不到,因?yàn)樗尤徊粫?huì)讀報(bào)紙上的故事,這太荒唐了,只是將書(shū)換成報(bào)紙,居然必須要修改Mother才能讀。假如以后需求換成雜志呢?換成網(wǎng)頁(yè)呢?還要不斷地修改Mother,這顯然不是好的設(shè)計(jì)。原因就是Mother與Book之間的耦合性太高了,必須降低他們之間的耦合度才行。
我們引入一個(gè)抽象的接口IReader。讀物,只要是帶字的都屬于讀物:
interface IReader{
public String getContent();
}
Mother類(lèi)與接口IReader發(fā)生依賴(lài)關(guān)系,而B(niǎo)ook和Newspaper都屬于讀物的范疇,他們各自都去實(shí)現(xiàn)IReader接口,這樣就符合依賴(lài)倒置原則了,代碼修改為:
class Newspaper implements IReader {
public String getContent(){
return "林書(shū)豪17+9助尼克斯擊敗老鷹……";
}
}
class Book implements IReader{
public String getContent(){
return "很久很久以前有一個(gè)阿拉伯的故事……";
}
}
class Mother{
public void narrate(IReader reader){
System.out.println("媽媽開(kāi)始講故事");
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é)果:
媽媽開(kāi)始講故事
很久很久以前有一個(gè)阿拉伯的故事……
媽媽開(kāi)始講故事
林書(shū)豪17+9助尼克斯擊敗老鷹……
這樣修改后,無(wú)論以后怎樣擴(kuò)展Client類(lèi),都不需要再修改Mother類(lèi)了。這只是一個(gè)簡(jiǎn)單的例子,實(shí)際情況中,代表高層模塊的Mother類(lèi)將負(fù)責(zé)完成主要的業(yè)務(wù)邏輯,一旦需要對(duì)它進(jìn)行修改,引入錯(cuò)誤的風(fēng)險(xiǎn)極大。所以遵循依賴(lài)倒置原則可以降低類(lèi)之間的耦合性,提高系統(tǒng)的穩(wěn)定性,降低修改程序造成的風(fēng)險(xiǎn)。
采用依賴(lài)倒置原則給多人并行開(kāi)發(fā)帶來(lái)了極大的便利,比如上例中,原本Mother類(lèi)與Book類(lèi)直接耦合時(shí),Mother類(lèi)必須等Book類(lèi)編碼完成后才可以進(jìn)行編碼,因?yàn)镸other類(lèi)依賴(lài)于Book類(lèi)。修改后的程序則可以同時(shí)開(kāi)工,互不影響,因?yàn)镸other與Book類(lèi)一點(diǎn)關(guān)系也沒(méi)有。參與協(xié)作開(kāi)發(fā)的人越多、項(xiàng)目越龐大,采用依賴(lài)導(dǎo)致原則的意義就越重大?,F(xiàn)在很流行的TDD開(kāi)發(fā)模式就是依賴(lài)倒置原則最成功的應(yīng)用。
傳遞依賴(lài)關(guān)系有三種方式,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構(gòu)造方法傳遞和setter方法傳遞,相信用過(guò)Spring框架的,對(duì)依賴(lài)的傳遞方式一定不會(huì)陌生。
在實(shí)際編程中,我們一般需要做到如下3點(diǎn):
- 低層模塊盡量都要有抽象類(lèi)或接口,或者兩者都有。
- 變量的聲明類(lèi)型盡量是抽象類(lèi)或接口。
- 使用繼承時(shí)遵循里氏替換原則。
依賴(lài)倒置原則的核心就是要我們面向接口編程,理解了面向接口編程,也就理解了依賴(lài)倒置。
相關(guān)文章
mybatis-plus實(shí)現(xiàn)邏輯刪除的示例代碼
本文主要介紹了mybatis-plus實(shí)現(xiàn)邏輯刪除的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
詳解SpringMVC學(xué)習(xí)系列之國(guó)際化
這篇文章主要介紹了詳解SpringMVC學(xué)習(xí)系列之國(guó)際化,詳細(xì)的介紹了關(guān)于瀏覽器,Session,Cookie,URL請(qǐng)求的國(guó)際化的實(shí)現(xiàn),有興趣的可以了解一下2017-07-07
Java設(shè)計(jì)模式之狀態(tài)模式State Pattern詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之狀態(tài)模式State Pattern,狀態(tài)模式允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變的時(shí)候改變其行為。這個(gè)對(duì)象看上去就像是改變了它的類(lèi)一樣2022-11-11
Java讀寫(xiě)鎖ReadWriteLock的創(chuàng)建使用及測(cè)試分析示例詳解
這篇文章主要為大家介紹了Java讀寫(xiě)鎖ReadWriteLock的創(chuàng)建使用及測(cè)試分析示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Spring Security OAuth 個(gè)性化token的使用
這篇文章主要介紹了Spring Security OAuth 個(gè)性化token的使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
Java實(shí)現(xiàn)將png格式圖片轉(zhuǎn)換成jpg格式圖片的方法【測(cè)試可用】
這篇文章主要介紹了Java實(shí)現(xiàn)將png格式圖片轉(zhuǎn)換成jpg格式圖片的方法,涉及java文件讀寫(xiě)及圖形創(chuàng)建等相關(guān)操作技巧,需要的朋友可以參考下2018-03-03
使用CXF和Jersey框架來(lái)進(jìn)行Java的WebService編程
這篇文章主要介紹了使用CXF和Jersey框架來(lái)進(jìn)行Java的WebService編程,Web service是一個(gè)平臺(tái)獨(dú)立的低耦合的自包含的基于可編程的web的應(yīng)用程序,需要的朋友可以參考下2015-12-12

