Java設計模式六大原則

凌浩雨發表於2017-09-20

Java 設計模式六大原則

單一職責原則

定義:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。

問題由來:類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時,有可能會導致原本執行正常的職責P2功能發生故障。

解決方案:遵循單一職責原則。分別建立兩個類T1、T2,使T1完成職責P1功能,T2完成職責P2功能。這樣,當修改類T1時,不會使職責P2發生故障風險;同理,當修改T2時,也不會使職責P1發生故障風險。

遵循單一職責原的優點有:

  • 可以降低類的複雜度,一個類只負責一項職責,其邏輯肯定要比負責多項職責簡單的多;
  • 提高類的可讀性,提高系統的可維護性;
  • 變更引起的風險降低,變更是必然的,如果單一職責原則遵守的好,當修改一個功能時,可以顯著降低對其他功能的影響。

需要說明的一點是單一職責原則不只是物件導向程式設計思想所特有的,只要是模組化的程式設計,都適用單一職責原則。

里氏替換原則

定義1:如果對每一個型別為 T1的物件 o1,都有型別為 T2 的物件o2,使得以 T1定義的所有程式 P 在所有的物件 o1 都代換成 o2 時,程式 P 的行為沒有發生變化,那麼型別 T2 是型別 T1 的子型別。

定義2:所有引用基類的地方必須能透明地使用其子類的物件。

問題由來:有一功能P1,由類A完成。現需要將功能P1進行擴充套件,擴充套件後的功能為P,其中P由原有功能P1與新功能P2組成。新功能P由類A的子類B來完成,則子類B在完成新功能P2的同時,有可能會導致原有功能P1發生故障。

解決方案:當使用繼承時,遵循里氏替換原則。類B繼承類A時,除新增新的方法完成新增功能P2外,儘量不要重寫父類A的方法,也儘量不要過載父類A的方法。

繼承包含這樣一層含義:父類中凡是已經實現好的方法(相對於抽象方法而言),實際上是在設定一系列的規範和契約,雖然它不強制要求所有的子類必須遵從這些契約,但是如果子類對這些非抽象方法任意修改,就會對整個繼承體系造成破壞。而里氏替換原則就是表達了這一層含義。

里氏替換原則通俗的來講就是:子類可以擴充套件父類的功能,但不能改變父類原有的功能。它包含以下4層含義:

  • 子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法。
  • 子類中可以增加自己特有的方法。
  • 當子類的方法過載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入引數更寬鬆。
  • 當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。

依賴倒置原則

定義:高層模組不應該依賴低層模組,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。

問題由來:類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的程式碼來達成。這種場景下,類A一般是高層模組,負責複雜的業務邏輯;類B和類C是低層模組,負責基本的原子操作;假如修改類A,會給程式帶來不必要的風險。

解決方案:將類A修改為依賴介面I,類B和類C各自實現介面I,類A通過介面I間接與類B或者類C發生聯絡,則會大大降低修改類A的機率。

依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象為基礎搭建起來的架構比以細節為基礎搭建起來的架構要穩定的多。在java中,抽象指的是介面或者抽象類,細節就是具體的實現類,使用介面或者抽象類的目的是制定好規範和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。

在實際程式設計中,我們一般需要做到如下3點:

  • 低層模組儘量都要有抽象類或介面,或者兩者都有。
  • 變數的宣告型別儘量是抽象類或介面。
  • 使用繼承時遵循里氏替換原則。

依賴倒置原則的核心就是要我們面向介面程式設計,理解了面向介面程式設計,也就理解了依賴倒置。

介面隔離原則

定義:客戶端不應該依賴它不需要的介面;一個類對另一個類的依賴應該建立在最小的介面上。

問題由來:類A通過介面I依賴類B,類C通過介面I依賴類D,如果介面I對於類A和類B來說不是最小介面,則類B和類D必須去實現他們不需要的方法。

解決方案:將臃腫的介面I拆分為獨立的幾個介面,類A和類C分別與他們需要的介面建立依賴關係。也就是採用介面隔離原則。

採用介面隔離原則對介面進行約束時,要注意以下幾點:

  • 介面儘量小,但是要有限度。對介面進行細化可以提高程式設計靈活性是不掙的事實,但是如果過小,則會造成介面數量過多,使設計複雜化。所以一定要適度。
  • 為依賴介面的類定製服務,只暴露給呼叫的類它需要的方法,它不需要的方法則隱藏起來。只有專注地為一個模組提供定製服務,才能建立最小的依賴關係。
  • 提高內聚,減少對外互動。使介面用最少的方法去完成最多的事情。

運用介面隔離原則,一定要適度,介面設計的過大或過小都不好。設計介面的時候,只有多花些時間去思考和籌劃,才能準確地實踐這一原則。

迪米特原則

定義:一個物件應該對其他物件保持最少的瞭解。

問題由來:類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。

解決方案:儘量降低類與類之間的耦合。

開閉原則

定義:一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。

問題由來:在軟體的生命週期內,因為變化、升級和維護等原因需要對軟體原有程式碼進行修改時,可能會給舊程式碼中引入錯誤,也可能會使我們不得不對整個功能進行重構,並且需要原有程式碼經過重新測試。

解決方案:當軟體需要變化時,儘量通過擴充套件軟體實體的行為來實現變化,而不是通過修改已有的程式碼來實現變化。

單一職責原則告訴我們實現類要職責單一;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向介面程式設計;介面隔離原則告訴我們在設計介面的時候要精簡單一;迪米特法則告訴我們要降低耦合。而開閉原則是總綱,他告訴我們要對擴充套件開放,對修改關閉。


相關文章