設計模式之六大原則(簡介)

weixin_34402408發表於2017-06-04

  設計模式是一套總結的理論,由Gang of Four總結出的一套可以反覆使用的軟體開發經驗,它們可以提高程式碼的重用性,增強程式碼的的可維護性,以及解決一系列的複雜問題。在提出設計模式之前,專家們首先提出了6大設計模式,也就是接下來要詳細介紹的內容。

1.單一職責原則(SRP)

  單一職責原則(Single Responsibility Principle)是一個備受爭議的設計原則。SRP的原話解釋是:There should never be more than one reason for a class to change. 意思也就是說通常情況下,應該有且僅有一個原因引起類的變更。

  • 單一職責原則具有如下優點:

  • 類的複雜性降低,實現什麼職責都有清晰明確的定義。

  • 可讀性提高

  • 可維護性提高。

  • 變更引起的風險降低。如果一個介面的單一職責做得好,那麼一個藉口的修改只對相應的實現類有影響,對其他介面無影響,這對系統的擴充套件性和可維護性都非常有益。

  • 單一職責原則的缺點:

  • 單一職責原則提出額一個編寫程式的標準,用“職責”或“變化原因”來衡量介面或類設計得是否優良,但“職責”和“變化原因”都是無法量化的,因專案而異,因環境而異。

  單一職責原則很難在專案中得到體現,單一職責原則使用與介面、類,同時也適用於方法。即一個方法儘可能只做一件事。

2.里氏替換原則(LSP)

  里氏替換原則(Liskov Substitution Principle)有兩種定義:
  第一種定義,也是最正宗的定義:If for each object o1 of type S there is an object 02 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when 01 is substituted for 02 then S is a subtype of T. (如果對每一個型別為S的物件o1,所有型別為T的物件o2,使得以T定義的所有程式P在所有的物件o1替換成o2時,程式P的行為不會發生變化,那麼型別S是型別T的子型別。)
  第二種定義:Functions that use pointers or references to base classes must be able to use objects of derived classed without knowing it.(所有引用基類的地方必須能透明地使用其子類物件。)通過俗點說,只要父類能出現的地方,子類就可以出現,而且替換為子類也不會產生任何錯誤或異常。
  里氏替換原則為良好的繼承定義了一套規範:

  • 子類必須完全實現父類的方法。
  • 子類可以有自己特有的屬性和方法。
  • 覆蓋或實現父類的方法時入參(前置條件)可以被放大。
  • 覆蓋或實現父類的方法時輸出結果可以被縮小。

  在專案中,採用里氏替換原則時,儘量避免子類的“個性”,因為一旦子類有了“個性”,把子類當做父類使用,子類的“個性”會被抹殺掉。而把子類作為一個業務來使用,則會讓程式碼之間的耦合關係變得撲朔迷離。

3.依賴倒置原則(DIP)

  依賴倒置原則(Dependence Inversion Principle) 的定義為:High level modules should not depend on low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.
通俗來說就是:

  • 高層模組不應該依賴於低層模組,兩者都應該依賴於其抽象。
  • 抽象不應該依賴於細節,細節應該依賴於抽象。

  依賴倒置原則在Java中的表現就是:模組間的依賴通過抽象發生,實現類之間不發生直接的依賴關係,其依賴關係是通過介面或抽象類產生的;介面或抽象類不依賴於實現類,實現類依賴介面或抽象類。一句話概括,就是:面向介面程式設計。

  依賴倒置原則可以減少類間耦合性,提高系統的穩定性,降低並行開發引起的風險,提高程式碼的可讀性和可維護性。依賴是可以傳遞的,物件的依賴傳遞方式(也叫依賴注入 Dependence Injection)有三種:

  • 建構函式方式傳遞依賴物件。
  • Setter方法傳遞依賴物件。
  • 介面宣告依賴物件,也叫介面注入。

  依賴倒置原則的本質就是通過抽象(介面或者抽象類)使各個類或模組的實現彼此獨立,不互相影響,實現模組之間的鬆耦合。如何在專案中使用這個規則呢?只要遵循以下幾個規則即可:

  • 每個類儘量都有介面或者抽象類,或者抽象類和介面兼具。
  • 變數的表面型別儘量是介面或抽象類。
  • 任何類都不應該從具體類派生。
  • 儘量不要覆寫基類的方法。
  • 結合里氏替換原則使用。

4.介面隔離原則

  定義:Clients should not be forced to depend upon interfaces that they don't use. The dependency of one class to another one should depend on the smallest possible interface. 即:客戶端不應該依賴它不需要的介面,類間的依賴關係應該建立在最小的介面上。概括地來說就是:建立單一介面,不要建立臃腫龐大的介面,介面儘量細化,同時介面中的方法應該儘量少。
介面隔離原則是對介面進行規範約束,其包含以下四層含義:

  • 介面儘量小。這裡的小時有限度的,首先就是不能違反單一職責原則。根據介面隔離原則拆分介面時,首先必須滿足單一職責原則。
  • 介面要高內聚。高內聚就是提高介面,類、模組的處理能力,減少對外的互動。
  • 定製服務。單獨為一個個體提供服務,採用定製服務必然要滿足一個要求:只提供訪問者需要的方法。
  • 介面設計是有限度的。介面的設計粒度越小,系統越靈活,這是個不爭的事實,但是靈活的同時也帶來了介面的複雜化,開發難度和可維護性降低。所以設計介面一定要注意適度。
    介面隔離原則是對介面的定義,同時也是對類的定義,介面和類儘量使用原子介面或原子類來組裝,實踐中可以根據以下幾個規則來衡量:
  • 一個介面只服務於一個子模組或業務邏輯。
  • 通過業務邏輯壓縮介面中的public方法。
  • 已經被汙染的介面,儘量去修改,若修改的風險較大,儘量採用介面卡模式進行轉化。
  • 瞭解環境,拒絕盲從。一切從實際需求出發。

5.迪米特法則

  迪米特法則(Law of Demeter, LoD)也成為最少知識原則(Least Knowledge Principle,LKP),雖然名字不同,但是描述的都是同一個規則:一個類應該對其他物件有最少的瞭解。通俗來說就是一個類應該對自己需要耦合或者呼叫的類知道的最少。
  使用迪米特法則可以堅持這樣一個原則:如果一個方法放在本類中,既不增加類間關係,也不對本類產生負面影響,那就放置在本類中。
  迪米特法則的核心思想就是類間解耦,弱耦合,只有弱耦合了以後,類的複用率才會提高,當然,解耦的同時需要注意,解耦也是有限度的。

6.開閉原則

  開閉原則的定義如下:Software entities like classes, modules and functions should e open for extension but closed for modifications.即一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。開閉原則可以提高複用性和維護性。
如何使用開閉原則?

  • 抽象約束。其包含三層含義:第一,通過介面或抽象類約束擴充套件,對擴充套件進行邊界限定,不允許出現在介面或抽象類中不存在的public方法;第二,引數型別、引用物件儘量使用介面或抽象類,而不是實現類;第三,抽象層儘量保持穩定,一旦確定即不允許修改。
  • 後設資料(metadata)控制模組行為。後設資料通俗來說就是配置引數。
  • 指定專案章程。
  • 封裝變化。對變化的封裝包含兩層含義:第一,將相同的變化封裝到一個介面或抽象類中;第二,將不同的變化封裝到不同的介面或抽象類中,不應該有兩個不同的變化出現在同一個介面或抽象類中。

《注》以上內容總結自秦小波-《設計模式之禪》,僅為個人學習筆記。

相關文章