天天看點

七大設計原則開閉原則依賴倒置原則單一職責原則接口隔離原則迪米特法則(最少知道原則)裡氏替換原則合成/複用原則

開閉原則

一個軟體實體如類、子產品和函數應該對擴充開放、修改關閉!

背景:一般情況下,在系統相對穩定的時候,一個Dao類都是通過實作一個抽象接口來完成一個Dao類,但是當我們對于某個Dao類的實作并不滿足。我們需要在原來的Dao基礎上新增方法或者子產品。對于專屬專用的接口自然比較容易,但是對于公共的接口或者職能清晰的接口,每一次的改變都是需要對系統的穩定和架構進行分析,對我們并不是那麼随便可以改的!

開閉原則則是指:在這種背景下,為了不破壞系統的穩定性,遵循其理對其進行擴充,而拒絕修改!

運用:

七大設計原則開閉原則依賴倒置原則單一職責原則接口隔離原則迪米特法則(最少知道原則)裡氏替換原則合成/複用原則

依賴倒置原則

依賴倒置原則(Dependence Inversion Principle)是程式要依賴于抽象接口,不要依賴于具體實作。簡單的說就是要求對抽象進行程式設計,不要對實作進行程式設計,這樣就降低了客戶與實作子產品間的耦合。

依賴倒置原則包含了兩層含義:

A.高層次的子產品不應該依賴于低層次的子產品,他們都應該依賴于抽象。

B.抽象不應該依賴于具體(細節),具體(細節)應該依賴于抽象。

高層次的子產品不應該依賴于低層次的子產品,他們都應該依賴于抽象

低層子產品也就是不可拆分的原子邏輯,高層子產品是N個原子邏輯的組合。

抽象在JAVA中指的是接口和抽象類,細節指的是實作類、實作接口、繼承抽象類的實作。

單一職責原則

單一職責原則(SRP:Single responsibility principle),它規定一個類應該隻有一個發生變化的原因。所謂職責是指類變化的原因。如果一個類有多于一個的動機被改變,那麼這個類就具有多于一個的職責。而單一職責原則就是指一個類或者子產品應該有且隻有一個改變的原因。

單一職責原則的好處:

  • 類的複雜性大大降低,每個類都有清楚的定義。
  • 提高可讀性。
  • 維護性高。
  • 變更時風險率降低。

接口隔離原則

接口隔離原則(Interface Segregation Principle ),用戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。

從定義上總結起來,要建立單一的接口,并且接口裡的方法越少越好,這裡說的接口指的是類接口,也就是Interface關鍵字定義的接口。

接口隔離原則和單一職責原則的差別:

單一職責原則指的是類、接口和方法的職責是單一的,強調的是職責,也就是說在一個接口裡,隻要職責是單一的,有10個方法也是可以的。

接口隔離原則指的是在接口中的方法盡量越來越少,接口隔離原則的前提必須先符合單一職責,在單一職責的前提下,接口盡量是單一接口。

迪米特法則(最少知道原則)

迪米特法則(Law of Demeter)又叫作最少知道原則(Least Knowledge Principle 簡寫LKP),就是說一個對象應當對其他對象有盡可能少的了解,不和陌生人說話。英文簡寫為: LoD.

迪米特法則的初衷在于降低類之間的耦合。由于每個類盡量減少對其他類的依賴,是以,很容易使得系統的功能子產品功能獨立,互相之間不存在(或很少有)依賴關系。

裡氏替換原則

裡氏替換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 裡氏替換原則中說,任何基類可以出現的地方,子類一定可以出現。 LSP是繼承複用的基石,隻有當衍生類可以替換掉基類,軟體機關的功能不受到影響時,基類才能真正被複用,而衍生類也能夠在基類的基礎上增加新的行為。

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

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

合成/複用原則

優先使用聚合或合成關系複用代碼。(通過繼承來複用代碼是面向對象程式設計中被濫用得最多的東西,因為所有的教科書都無一例外的對繼承進行了鼓吹進而誤導了初學者,類與類之間簡單的說有三種關系,Is-A關系、Has-A關系、Use-A關系,分别代表繼承、關聯和依賴。其中,關聯關系根據其關聯的強度又可以進一步劃分為關聯、聚合和合成,但說白了都是Has-A關系,合成聚合複用原則想表達的是優先考慮Has-A關系而不是Is-A關系複用代碼,原因嘛可以自己從百度上找到一萬個理由,需要說明的是,即使在Java的API中也有不少濫用繼承的例子,例如Properties類繼承了Hashtable類,Stack類繼承了Vector類,這些繼承明顯就是錯誤的,更好的做法是在Properties類中放置一個Hashtable類型的成員并且将其鍵和值都設定為字元串來存儲資料,而Stack類的設計也應該是在Stack類中放一個Vector對象來存儲資料。記住:任何時候都不要繼承工具類,工具是可以擁有并可以使用的,而不是拿來繼承的。)