設計模式的分類和六大原則

Renly_wen發表於2021-11-15

設計模式的分類

總的來說,設計模式分位三大類:

  1. 建立型模式(5種)
    工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式
  2. 結構型模式(7種)
    介面卡模式、裝飾器模式、代理模式、外觀模式(門面模式)、橋接模式、組合模式、享元模式
  3. 行為型模式(11種)
    策略模式、模板方法模式、觀察者模式、迭代器模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式

六大原則

總原則:開閉原則

定義:一個軟體實體應該對擴充套件開放,對修改關閉。

當一個軟體實體需要擴充套件的時候,不要去修改原有的程式碼,而是去擴充套件原有的程式碼。
開閉原則是最基礎的一個原則,六大原則都是開閉原則的具體形態。
採用開閉原則的原因:

  1. 避免測試複雜化:
    通過擴充套件實現變化,測試只需要對新增類進行單元測試即可,只需要保證新類提供的方法正確就行。

  2. 提高程式碼複用性:
    避免以後為了修改一個微小的缺陷或增加新功能,卻要在整個專案中到處查詢相關的程式碼逐一修改。

  3. 提高可維護性:
    開發新功能時,擴充套件一個類往往比修改一個類更容易。

1. 單一職責原則

定義:有且僅有一個原因引起類的變更

優點:

  1. 類的複雜性降低
  2. 可讀性提高
  3. 易維護
  4. 修改類引起的風險降低

臨界點:

  1. 過度的劃分會使類劇增,增加系統的複雜度

2. 里氏代換原則

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

優點:

  1. 提高程式碼的重用性
  2. 提高程式碼的可擴充性
  3. 提高專案的開放性

缺點:

  1. 記成是入侵式的,只要繼承,就有父類的屬性和方法
  2. 降低程式碼靈活性,子類多了父類的約束
  3. 增強耦合性,父類的常量/變數/方法改動時,必須考慮子類的修改

四層含義:

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

3. 依賴倒轉原則

定義:

  1. 高層模組不應該依賴低層模組,兩者都要依賴其抽象(模組間的依賴通過抽象產生,實現類不直接發生依賴)
  2. 抽象不應該依賴細節(介面或者抽象類不依賴實現類)
  3. 細節可以依賴抽象(實現類依賴介面或抽象類)

處理:

  1. 每個類儘量都有介面或者抽象類
  2. 變數的表面型別儘量是介面或者抽象類
  3. 任何類都不應該從具體類派生
  4. 儘量不要複寫基類已實現的方法
  5. 結合里氏替換原則使用

4. 依賴倒轉原則

定義:客戶端不應該依賴不需要的介面,類之間的依賴關係應該建立在最小的介面上

四層含義:

  1. 介面儘量小,不要出現臃腫的介面
  2. 介面要高內聚
  3. 只提供訪問者需要的方法,每個介面中不存在子類用不到卻必須要實現的內容,可以將介面拆分
  4. 介面設計限度:設計粒度越小系統越靈活,結構會越複雜,可維護性降低

處理:

  1. 一個介面只服務一個子模組或者業務邏輯
  2. 儘量壓縮介面內的方法,保證都是有用的,避免臃腫
  3. 已被汙染的介面儘量去修改,若變更風險大,採用介面卡模式轉化處理
  4. 深入瞭解業務邏輯

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

定義:一個物件應該對其他物件有最小的瞭解(低耦合)

含義:

  1. 方法儘量不引入類中不存在的物件
  2. 儘量不要暴露過多public方法和非晶態public變數,儘量內斂
  3. 如果一個方法放在本類中,既不增加類間的關係,也不對本類產生負面影響,就可放置在本類中

總結:

核心觀念就是類間解耦,低耦合。其負面影響就是產生了大量的中轉或者跳轉類,導致系統複雜性提高,也為維護帶來了難度。需要反覆權衡,既做到結構清晰,又要高內聚低耦合。
如果一個類需要跳轉兩次以上才能訪問到另一個類,就需要想辦法重構了。

6. 合成複用原則

定義:是在一個新的物件裡面使用一些已有的物件,使其成為新物件的一部分。新物件通過委派達到複用已有功能的效果。

優點:

使用物件的合成/聚合將有助於保持每個類被封裝,並被集中在單個任務上。這樣類和整合層次會保持較小規模,並且不太可能增長為不可控制的龐然大物

缺點:

通過這種方式複用建造的系統會有較多的物件需要管理;為了能將多個不同的物件作為組合塊來使用,必須仔細地對介面進行定義

簡單地說:儘量首先使用合成/聚合的方式,而不是使用繼承

相關文章