溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java依賴倒轉(zhuǎn)原則_動力節(jié)點Java學(xué)院整理

發(fā)布時間:2020-10-02 17:02:36 來源:腳本之家 閱讀:95 作者:zhengzhb 欄目:編程語言

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

問題由來:類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類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()); 
 } 
} 

運行結(jié)果:

媽媽開始講故事

很久很久以前有一個阿拉伯的故事……

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

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()); 
 } 
} 

運行結(jié)果:

媽媽開始講故事
很久很久以前有一個阿拉伯的故事……
媽媽開始講故事

林書豪17+9助尼克斯擊敗老鷹……   

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

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

傳遞依賴關(guān)系有三種方式,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構(gòu)造方法傳遞和setter方法傳遞,相信用過Spring框架的,對依賴的傳遞方式一定不會陌生。
在實際編程中,我們一般需要做到如下3點:

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

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

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI