本人主要講述設計模式怎麼去選擇,這僅僅是不知從何下手提供一個抓手的東西,並不是銀彈。常想、多用,積累經驗後,方可靈活運用,做到無模式勝有模式,才可能會在複雜場景中,設計出高質量的系統。
設計模式的選擇是一個從問題到解決方案的遞進過程。通過明確問題類型、分析目標特性、遵循設計原則以及結合場景需求,可以高效地篩選出最佳設計模式,從而達到優化系統設計,提升代碼質量和可維護性。設計模式不僅是一種工具,更是一種面向對象程序設計的思維方式,能幫助開發者構建更加穩定和易於維護的軟件系統。
這篇文章花了挺多時間去整理的,還請耐心看完。
先説整體上,怎麼考慮,怎麼選擇。
1.設計模式選擇的綜合指南
1.1. 核心決策框架
- 問題驅動分類法
將系統問題歸類為三大場景,形成決策起點:
- 創建型問題:對象如何誕生?(如電商購物車實例的全局唯一性 → 單例模式)
- 結構型問題:對象如何組織?(如動態擴展訂單附加服務 → 裝飾者模式)
- 行為型問題:對象如何協作?(如用户操作觸發多模塊聯動 → 觀察者模式)
- 原則約束檢查表
選擇模式時需通過設計原則驗證:
- 單一職責:該模式是否讓每個類/模塊更專注?(如狀態模式分離狀態邏輯與主業務)
- 開閉原則:新增功能是否無需修改既有代碼?(如裝飾者模式疊加功能不破壞原有結構)
- 依賴倒置:是否通過接口而非具體實現交互?(如抽象工廠模式隔離具體產品類)
- 里氏替換原則:具體實現類的切換是否影響程序正常使用?(如策略模式支持動態切換具體實現類)
1.2. 模式選擇進階策略
- 模式組合技
- 動態創建+行為擴展:工廠方法+策略模式
(示例:支付系統中,工廠創建支付處理器,策略模式切換算法) - 狀態管理+消息通知:狀態模式+觀察者模式
(示例:訂單狀態變更時,自動觸發庫存更新和用户通知)
- 反模式預警
強調設計模式中設計思想的運用
| 陷阱 | 後果 | 解決方案 |
|---|---|---|
| 單例濫用 | 測試困難、隱藏依賴 | 依賴注入+工廠模式(如Spring框架) |
| 過度裝飾者嵌套 | 調試鏈路複雜 | 合理控制層級,結合組合模式 |
| 觀察者內存泄漏 | 未及時取消訂閲 | 弱引用+生命週期管理 |
- 性能權衡指南
- 空間換時間:享元模式共享對象減少內存重複--如遊戲中的樹木渲染共享紋理
- 時間換靈活:代理模式增加間接層帶來性能損耗--需評估延遲是否在可接受範圍
- 模式輕量化:函數式替代方案--如Lambda替代策略模式接口
2. 設計模式決策樹(23種)
細緻到每個設計模式的特點,通過問題類型和場景特徵,逐步定位適合的設計模式:
2.1. 第一步:確定核心問題類型
這個前面也已經提到過的了。
- 是否需要創建/管理對象?→ 創建型模式(6種)
- 是否需要組織對象結構? → 結構型模式(7種)
- 是否需要定義對象間協作?→ 行為型模式(11種)
2.2. 第二步:細化選擇路徑
1. 創建型模式(5種)
問題:如何高效、靈活地創建對象?
是否需要控制對象實例數量和提供全局訪問點?
├─ 是 → 單例模式(Singleton)
└─ 否 →
是否需要分步構造複雜對象?
├─ 是 → 建造者模式(Builder)
└─ 否 →
是否通過克隆快速創建對象(避免高成本構造)?
├─ 是 → 原型模式(Prototype)
└─ 否 →
是否需要在不暴露具體類的前提下,動態選擇實例化的類?
├─ 是 → 工廠方法模式(Factory Method)
└─ 否 →
是否需要創建一組相關對象,並確保它們協同工作?
├─ 是 → 抽象工廠模式(Abstract Factory)
└─ 否 → 簡單工廠 或 直接創建
2. 結構型模式(7種)
問題:如何優化對象之間的組合與關係?
是否需要擴展對象功能且不影響現有代碼?
├─ 是 →
│ 是否需動態疊加功能?
│ ├─ 是 → 裝飾者模式(Decorator)
│ └─ 否 → 適配器模式(Adapter)
└─ 否 →
是否需要簡化複雜子系統?
├─ 是 → 外觀模式(Facade)
└─ 否 →
是否需要解耦抽象與實現,以支持獨立變化?
├─ 是 → 橋接模式(Bridge)
└─ 否 →
是否需要共享大量對象以減少內存資源?
├─ 是 → 享元模式(Flyweight)
└─ 否 →
是否需要組合對象為樹形結構(“部分-整體”的層次關係)?
├─ 是 → 組合模式(Composite)
└─ 否 →
是否需要代理控制訪問或優化性能?
├─ 是 → 代理模式(Proxy)
└─ 否 →
3. 行為型模式(11種)
問題:如何管理對象間的協作與責任分配?
是否需要動態切換一組算法?
├─ 是 → 策略模式(Strategy)
└─ 否 →
是否通過狀態驅動行為?
├─ 是 → 狀態模式(State)
└─ 否 →
是否需要集中管理對象間複雜交互?
├─ 是 → 中介者模式(Mediator)
└─ 否 →
是否需要支持請求的撤銷/重做?
├─ 是 → 備忘錄模式(Memento)
└─ 否 →
是否需要將請求封裝為對象(支持參數化、隊列化)?
├─ 是 → 命令模式(Command)
└─ 否 →
是否需要被觀察的對象變化後,會自動通知多個訂閲者?
├─ 是 → 觀察者模式(Observer)
└─ 否 →
是否需要由多個對象依次處理請求?
├─ 是 → 責任鏈模式(Chain of Responsibility)
└─ 否 →
是否需要定義操作步驟/算法骨架,並允許子類重寫具體細節?
├─ 是 → 模板方法模式(Template Method)
└─ 否 →
是否需要遍歷集合對象?
├─ 是 → 迭代器模式(Iterator)
└─ 否 →
是否需要分離數據結構和操作行為?
├─ 是 → 訪問者模式(Visitor)
└─ 否 →
是否需要解釋和處理某種語言或表達式的語法規則?
├─ 是 → 解釋器模式(Interpreter)
└─ 否 →
注:行為型模式的選擇並無嚴謹的先後順序。
2.3. 決策樹使用建議
設計模式決策樹的核心邏輯是:
問題分類 → 目標匹配 → 原則驗證。
在實際開發中需結合具體場景靈活調整,最終目標是寫出高內聚、低耦合、可重用、易擴展、易維護和高性能的代碼。 通過刻意練習(如重構既有代碼、閲讀框架源碼),可逐步培養模式選擇的直覺。
避免教條主義:模式是工具而非規則,例如簡單場景無需強制使用設計模式,而複雜場景需要多種模式相互配合和模式創新。
3. 總結
設計模式的選擇如同烹飪調味——需要根據食材特性(系統需求)、食客口味(團隊能力)、廚房條件(技術棧)綜合決策。關鍵在於:
- 保持問題敏感度:從代碼異味(如巨型類、擴散式修改)中發現模式應用契機
- 掌握模式本質:理解模式背後的抽象原則而非具體實現
- 培養架構直覺:通過閲讀優秀源碼(如Spring、Netty)積累模式使用經驗
最終目標不是成為模式的奴隸,而是讓模式成為手中游刃有餘的設計語言,構建出兼具彈性與簡潔性的軟件系統。
通過項目開發,積累經驗後,你會逐漸能根據項目的具體需求,靈活運用合適的設計模式。
需要查看往期設計模式文章的,可以在個人主頁中或者文章開頭的集合中查看,可關注我,持續更新中。。。
後續會分享:
秘籍1>>掌握設計模式:23種經典模式實踐、選擇、價值與思想.pdf
秘籍2>>設計模式實戰項目:markdown文本編輯器軟件開發(開放所有源代碼)
超實用的SpringAOP實戰之日誌記錄
2023年下半年軟考考試重磅消息
通過軟考後卻領取不到實體證書?
計算機算法設計與分析(第5版)
Java全棧學習路線、學習資源和麪試題一條龍
軟考證書=職稱證書?
軟考中級--軟件設計師毫無保留的備考分享