[設計模式]1_設計模式概覽

摘要:設計模式原則、設計模式的劃分與簡要概括,怎么使用重構獲得設計模式并改善代碼的壞味道。

本篇作概覽與檢索用,后續結合源碼進行具體模式深入學習。

目錄

1、設計模式原理

核心原則(語言無關)

本質原理圖

原則關聯矩陣

2、設計模式分類

1. 創建型模式

2. 結構型模式

3. 行為型模式

3、重構獲得模式

重構關鍵技法

靜態——>動態

早綁定——>晚綁定

繼承——>組合

編譯時依賴——>運行時依賴

緊耦合——>松耦合

生產設計的原則傾向


什么樣的代碼算是好的代碼呢?同好的服務一樣(此處強行關聯 《[微服務設計]1_微服務》)——功能正確、高效、可維護性強、健壯抗壓、寫作流暢。也可以總的來說,低耦合高內聚的高質量可維護代碼,就是好的代碼。

那么,有沒有一些規范可以遵循的呢?

有的,設計模式就是這樣的指導規范。

1、設計模式原理

核心原則(語言無關)

眾所周知,設計模式有一些原則可以遵守:

單一職責一個模塊/類應僅負責一個職責降低模塊間耦合,提升可維護性。

里氏替換:所有引用基類的地方必須能透明地使用子類對象。這樣利于抽象與類型封裝。

開放封閉:對修改封閉、對拓展開放。

迪米特減少對象間不必要的直接交互,降低耦合,提高模塊獨立性

接口隔離原則客戶端不應依賴未使用的接口將大接口拆分為小的、高內聚的接口。

依賴倒置:高層模塊不應該依賴于底層模塊,轉換為二者都依賴于抽象。具體來說就是針對接口編程,而不是針對具體實現,這樣可以減少各部分依賴關系,這也面向對象設計的亮點。

還有優先使用對象組合而不是類繼承等等……

總的來說:從通用核心原則到實現層原則再到構造策略相關的原則,均追求代碼模塊的低耦合高內聚,降低復雜度。

本質原理圖

原則關聯矩陣

原則

變化控制

認知簡化

系統彈性

典型模式

單一職責(SRP)

外觀模式

開放封閉(OCP)

極高

極高

策略模式、 裝飾器模式

里氏替換(LSP)

組合模式、代理模式

接口隔離(ISP)

極高

適配器模式、中介模式

依賴倒置(DIP)

極高

橋接模式、依賴注入模式

組合優先

極高

享元模式,職責鏈模式

2、設計模式分類

Gang of Four(四人組,GOF) 在經典著作《設計模式:可復用面向對象軟件的基礎》中提出的23種設計模式的分類方式,按功能和用途分為三大類——創建型、結構型、行為型。

1. 創建型模式

目的:解決對象的創建問題,封裝實例化邏輯,提升代碼復用性和靈活性。

核心思想:將對象的創建與使用解耦,通過統一接口或模板控制對象實例化過程。

  • 工廠方法 (Factory Method): 定義一個創建對象的接口,但由子類決定要實例化的類。工廠方法將類的實例化推遲到子類。

  • 抽象工廠 (Abstract Factory): 提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們的具體類。

  • 原型 (Prototype): 通過復制現有對象來創建新對象,而不是通過創建新實例。

  • 建造者 (Builder): 用于構建一個復雜對象的表示。使用多個步驟構建該對象,可以將構建過程與其表示分離。

2. 結構型模式

目的:處理類與對象的組合,優化系統結構,提高模塊間的解耦性。

關注如何將對象組合成更大的結構,處理類和對象的關系,以實現更大的功能。

核心思想:通過組合、繼承或接口,調整類與對象的結構,增強系統的靈活性和擴展性。

  • 裝飾器 (Decorator): 動態地給對象添加額外的職責或行為,而不影響其他對象的功能。

  • 橋接 (Bridge): 將抽象部分與其實現部分分離,使它們可以獨立變化。

  • 外觀 (Facade): 為一組接口提供一個統一的高層接口,使得子系統更易使用。

  • 代理 (Proxy): 為其他對象提供一種代理以控制對這個對象的訪問。

  • 中介者 (Mediator): 用于減少對象之間的通信復雜性,避免對象之間的直接引用。

  • 適配器 (Adapter): 在不修改源代碼的情況下,允許將不兼容的接口連接起來。

  • 享元 (Flyweight): 通過共享對象來支持大量細粒度的對象,減少內存消耗。

3. 行為型模式

目的:定義對象間的通信機制,管理算法或職責的動態變化。

核心思想:通過解耦對象間的直接依賴,實現行為的動態組合、算法替換或事件驅動。

  • 模板方法 (Template Method): 在一個方法中定義一個操作的整體結構,而將某些步驟的實現延遲到子類中。

  • 策略 (Strategy): 定義一系列算法,將每個算法封裝起來,并使它們可以互換,從而使其獨立于使用它的客戶端。

  • 觀察者/事件 (Observer/Event): 定義對象間的一對多依賴,確保當一個對象變化時,其依賴對象也會被通知并自動更新。

  • 命令 (Command): 將請求封裝為對象,從而允許參數化客戶、隊列請求以及記錄請求日志。

  • 訪問者 (Visitor): 表示一個作用于某種對象結構中的各元素的操作,并使其可以在不改變元素類的前提下定義新的操作。

  • 備忘錄 (Memento): 捕獲一個對象的內部狀態,以便在以后恢復對象的狀態,而不暴露對象的實現細節。

  • 狀態 (State): 讓一個對象在其內部狀態改變時改變其行為,對象將表現得像是它的類發生了改變。

  • 組合 (Composite): 將對象組合成樹形結構以表示部分-整體的層次,并使客戶端對單個對象和組合對象的使用保持一致。

  • 迭代器 (Iterator): 提供一種方式訪問一個集合對象中的元素,而無需暴露它的內部表示。

  • 責任鏈 (Chain of Responsibility): 將請求的發送者和接收者解耦。將多個對象連成一條鏈,并沿著這條鏈傳遞請求,直到有一個對象處理它。

  • 解釋器 (Interpreter): 為了一種語言定義一個文法,并提供一個解釋器來使用該文法。

3、重構獲得模式

需要強調的是:

設計模式是循序漸進的,如同架構設計一樣,沒有一步到位的設計模式,也少有單一的設計模式,要掌握應用時間、地點。

應對變化,提高復用,尋找變化點。

設計模式應在變化點處應用:設計模式是對動態變化點的設計,在變化、穩定中尋找隔離點,來分離他們,從而管理變化,以穩控變。

沒有一個穩定的點,設計模式就沒有意義。

設計模式有23種,慢慢理解嘛。

重構關鍵技法

在《重構-改善既有代碼的設計》一書中,作者Martin Fowler有提到一些有效的重構手法,重構時遵守設計原則。

壞味道

重構手法

重復代碼(Duplicated Code)

提煉函數、參數化、提取類。

過長函數(Long Method)

提煉函數、內聯臨時變量。

過大類(Large Class)

提煉類、搬移函數/字段。

數據泥團(Data Clumps)

封裝為獨立類。

條件邏輯復雜(Switch/If)

以多態取代條件、引入策略模式。

被拒絕的遺贈

函數下移、以委托取代子類。

冗余注釋(Comments)

通過代碼重構讓注釋多余(如提煉函數明確意圖)。

技法對應原則如下:

靜態——>動態

更好地適應變化與減少重復代碼:動態結構可以通過配置或者接口靈活調整,可以服用邏輯,避免靜態編碼導致的重復。

設計模式

如策略模式(通過接口定義算法族,運行時選擇具體策略)、觀察者模式(事件驅動的動態通知機制)

重構手法

替換條件分支為多態(如將if-else替換為不同子類實現)。

引入參數化配置(如通過配置文件動態加載行為)。

示例如下:

// 靜態:硬編碼的條件判斷
public void calculateTax(double income) {if (country == "USA") {// 美國稅率邏輯} else if (country == "China") {// 中國稅率邏輯}
}// 動態:使用策略模式
interface TaxStrategy {double calculate(double income);
}
class USATax implements TaxStrategy { ... }
class ChinaTax implements TaxStrategy { ... }public void calculateTax(TaxStrategy strategy, double income) {return strategy.calculate(income);
}

早綁定——>晚綁定

通過接口和運行時決策增強靈活性。

定義與背景

  • 早綁定:在編譯時確定對象類型和方法調用(如直接調用具體類的方法)。

  • 晚綁定:在運行時動態確定對象類型和方法調用(如通過接口或多態)。

為什么需要轉向晚綁定?

  • 靈活性:允許在運行時替換實現,支持擴展和插件化。

  • 解耦:調用者無需依賴具體實現類,僅依賴抽象接口。

如何實現?

  • 面向接口編程:定義接口,由子類實現不同行為。

  • 多態與虛函數:通過基類指針/引用調用虛方法。

  • 依賴注入:通過外部配置或工廠動態注入對象。

// 早綁定:直接依賴具體類
public void sendEmail(Email email) {EmailSender sender = new GmailSender();sender.send(email);
}// 晚綁定:通過接口實現多態
public interface EmailSender {void send(Email email);
}
public class GmailSender implements EmailSender { ... }
public class OutlookSender implements EmailSender { ... }public void sendEmail(Email email, EmailSender sender) {sender.send(email); // 運行時決定具體實現
}

繼承——>組合

用組合替代繼承,避免層級過深。

定義與背景

  • 繼承:通過繼承復用父類代碼,子類與父類形成“is-a”關系。

  • 組合:通過組合其他對象復用功能,形成“has-a”關系。

為什么需要轉向組合?

  • 減少耦合:繼承導致子類與父類高度耦合,組合則通過接口或抽象類解耦。

  • 避免繼承樹復雜化:組合允許動態替換組件,而繼承的層級過深易導致維護困難。

如何實現?

  • 組合復用:將功能封裝為獨立對象,通過字段或方法參數組合使用。

  • 策略模式:通過組合不同策略對象實現不同行為。

// 繼承:硬編碼行為
class Animal {void move() { ... }
}
class Bird extends Animal { ... }
class Fish extends Animal { ... }// 組合:通過接口解耦
interface MovementStrategy {void move();
}
class Bird {private MovementStrategy movement;public Bird(MovementStrategy movement) {this.movement = movement;}void fly() {movement.move(); // 組合不同策略}
}

編譯時依賴——>運行時依賴

將依賴關系移到運行時,提高可測試性和擴展性。

定義與背景

  • 編譯時依賴:依賴關系在代碼中硬編碼(如直接new具體類)。

  • 運行時依賴:依賴關系在運行時動態注入(如通過配置或工廠)。

為什么需要轉向運行時依賴?

  • 可測試性:便于通過模擬對象(Mock)進行單元測試。

  • 靈活性:可替換依賴實現,無需修改代碼。

如何實現?

  • 依賴注入(DI):通過構造函數、方法或字段注入依賴對象。

  • 工廠模式:通過工廠類動態創建對象。

// 編譯時依賴:硬編碼依賴
class Service {private Database database = new MySQLDatabase();void doWork() {database.query();}
}// 運行時依賴:通過構造函數注入
class Service {private Database database;public Service(Database database) {this.database = database; // 運行時注入}void doWork() {database.query();}
}

緊耦合——>松耦合

通過抽象接口和事件機制降低模塊間依賴。

定義與背景

  • 緊耦合:類之間直接依賴具體實現,修改一個類可能影響多個類。

  • 松耦合:通過抽象接口或事件機制降低依賴,僅依賴抽象。

為什么需要轉向松耦合?

  • 可維護性:降低修改代碼的風險,模塊獨立。

  • 擴展性:新增功能無需修改現有代碼(開閉原則)。

如何實現?

  • 接口與抽象類:定義抽象接口,類僅依賴接口。

  • 觀察者模式:通過事件機制解耦對象間的直接通信。

  • 發布-訂閱模式:對象通過中間事件總線通信。

// 緊耦合:直接調用具體類
class Button {void onClick() {Text text = new Text();text.update();}
}// 松耦合:通過接口解耦
interface Updatable {void update();
}
class Button {private Updatable listener;public Button(Updatable listener) {this.listener = listener;}void onClick() {listener.update();}
}

總結一下核心思想是動態化、低耦合高內聚、保證可讀性與可維護性。

生產設計的原則傾向

低耦合、高內聚是軟件設計的核心原則,但并非所有設計場景的最優先考慮的事情。

比如業務服務設計中,優先考慮組織架構所需求的迭代或者用戶需求和業務目標,在架構設計中,優先考慮系統性能、可維護性。

需要依據具體場景靈活變動。

再次強調,無必要修改的“完美主義”重構,設計模式也不是最優先考慮的,優先完成,優先保證代碼清晰。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/73456.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/73456.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/73456.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言數據類型取值范圍及格式化符號

一、數據類型取值范圍與格式化輸出符號表格 數據類型大小&#xff08;字節&#xff09;取值范圍格式化輸出符號char1-128到127<br>或0到255&#xff08;如果聲明為unsigned char&#xff09;%c (字符)<br>%hhu (無符號)signed char1-1.2810到1.2710%hhd (有符號)u…

2024華東師范大學計算機復試上機真題

2024華東師范大學計算機復試機試真題 2023華東師范大學計算機復試機試真題 2022華東師范大學計算機復試機試真題 2024華東師范大學計算機復試上機真題 2023華東師范大學計算機復試上機真題 2022華東師范大學計算機復試上機真題 在線評測&#xff1a;傳動門&#xff1a;pgcode…

星越L_內后視鏡使用講解

目錄 1內后視鏡角度調節 2,防炫目功能

Spring Boot應用首次請求性能優化實戰:從數據庫連接池到JVM調優

目錄 問題現象與背景分析性能瓶頸定位方法論數據庫連接池深度優化Spring Bean生命周期調優JVM層性能預熱策略全鏈路監控體系建設生產環境驗證方案總結與擴展思考1. 問題現象與背景分析 1.1 典型問題場景 在某互聯網金融項目的Spring Boot應用上線后,運維團隊發現一個關鍵現象…

【深度解析:以“不要的心態”獲取所求的本質邏輯】

深度解析&#xff1a;以“不要的心態”獲取所求的本質邏輯 一、文化基因&#xff1a;禮讓傳統與權力合法性的雙重編碼 儒家倫理的深層滲透 孔子提出"禮之用&#xff0c;和為貴"&#xff0c;將"辭讓"納入"仁義禮智信"的道德體系。《禮記》明確記…

C++【類和對象】(結束篇)

C類和對象 1.static成員2.友元3.內部類4.匿名對象5.對象拷貝時的編譯器優化 1.static成員 用static修飾的成員變量叫做靜態成員變量&#xff0c;靜態成員一定要在類外進行初始化。靜態成員變量為所有類的共享&#xff0c;放入靜態區&#xff0c;不屬于某個具體對象&#xff0c…

每日一題---腐爛的蘋果(廣度優先搜索)

腐爛的蘋果 給定一個 nm nm 的網格&#xff0c;其中每個單元格中可能有三種值中的一個 0 , 1 , 2。 其中 0 表示這個格子為空、1 表示這個格子有一個完好的蘋果&#xff0c;2 表示這個格子有一個腐爛的蘋果。 腐爛的蘋果每分鐘會向上下左右四個方向的蘋果傳播一次病菌&…

maven筆記

maven介紹和作用 Maven 是一款為 Java 項目構建管理、依賴管理的工具&#xff08;軟件&#xff09;&#xff0c;使用 Maven 可以自動化構建、測試、打包和發布項目&#xff0c;大大提高了開發效率和質量。 主要作用的理解&#xff1a; 依賴管理&#xff1a; 在編寫項目時我…

模板-C++提高編程

C的一種編程思想稱為泛型編程&#xff0c;用到的技術就是模板 C提供兩種模板&#xff1a;函數模板和類模板。 1.函數模板 1.函數模板作用 建立一個通用函數&#xff0c;其返回值類型和形參類型可以用一個虛擬的類型來代替,提高代碼復用性&#xff0c;將類型參數化。 2.語法…

基于Asp.net的物流配送管理系統

作者&#xff1a;計算機學姐 開發技術&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源碼”。 專欄推薦&#xff1a;前后端分離項目源碼、SpringBoot項目源碼、Vue項目源碼、SSM項目源碼、微信小程序源碼 精品專欄&#xff1a;…

順序表和鏈表的對比(一)

前言 今天給小伙伴們分享的是在數據結構中順序表和鏈表的對比。它們在計算機科學和軟件開發中具有廣泛的應用&#xff0c;是理解更復雜數據結構&#xff08;如棧、隊列、樹、圖等&#xff09;的基礎。這次將會給大家從定義初始化&#xff0c;以及功能增刪查改上進行詳細對比&a…

星越L_外后視鏡使用講解

目錄 1.外后視鏡調節 2后視鏡折疊 3.后視鏡加熱 1.外后視鏡調節 L控制左邊后視鏡調節,上下撥動調整視野,一般此鏡左右21分,上下55開。 R控制左邊后視鏡調節,上下撥動調整視野,一般此鏡左右13分,上下55開。 2后視鏡折疊 車輛解鎖自動展開 車輛關閉自動折疊 嚴寒天氣…

DevOps實踐:持續集成與持續部署完全指南

文章目錄 引言&#xff1a;從人工到自動化的進化革命一、CI/CD核心認知升級1.1 持續集成 vs 持續部署 vs 持續交付1.2 中小團隊為什么要實施CI/CD&#xff1f; 二、CI/CD工具鏈選型指南2.1 中小團隊推薦技術棧2.2 工具對比決策矩陣 三、實戰五步構建企業級流水線3.1 基礎環境搭…

【數據結構】數據結構,算法 概念

0.本篇問題&#xff1a; 數據、數據元素、數據對象、數據項之間的基本關系&#xff1f;ADT是什么&#xff1f;數據結構的三要素&#xff1f;數據的邏輯結構有哪些&#xff1f;數據的存儲結構有哪些&#xff1f;算法的五個特征&#xff1f;O(1) O(logn) O(n^n) O(n) O(n^2…

同步Oracle及mysql至KADB的KFS配置文件參考

Oracle源端flysync.ini文件 注意&#xff1a;oracle用戶名大寫 mysql源端flysync.ini文件 附&#xff1a;目標端KADB的flysync.ini文件 [m_kes_3113] 源端為KES kufl-port3113 datasource-typekingbase rolemaster replication-host10.4.43.53 replication-port54321 …

PECL(Positive Emitter-Coupled Logic)電平詳解

一、PECL電平的定義與核心特性 PECL&#xff08;正射極耦合邏輯&#xff09;是一種基于 射極耦合邏輯&#xff08;ECL&#xff09;技術 的高速差分信號標準&#xff0c;采用 正電源供電&#xff08;如5V或3.3V&#xff09;。其核心特性包括 高速傳輸、低噪聲、強抗干擾能力&am…

以 ArcGIS Pro 為筆,繪就水墨地圖畫卷

一、引言 水墨畫&#xff0c;作為中國傳統繪畫藝術的瑰寶&#xff0c;以其獨特的韻味和表現力&#xff0c;在藝術領域占據著重要地位。它通過水與墨的交融&#xff0c;展現出山水之間的靈動與韻味。 而將這種藝術形式與現代地理信息系統&#xff08;GIS&#xff09;技術相結合…

軟考網絡安全專業

隨著信息技術的迅猛發展&#xff0c;網絡安全問題日益凸顯&#xff0c;成為社會各界普遍關注的焦點。在這樣的背景下&#xff0c;軟考網絡安全專業應運而生&#xff0c;為培養高素質的網絡安全人才提供了有力支撐。本文將對軟考網絡安全專業進行深入剖析&#xff0c;探討其在信…

在線 SQL 轉 SQLAlchemy:一鍵生成 Python 數據模型

一款高效的在線 SQL 轉 SQLAlchemy 工具&#xff0c;支持自動解析 SQL 語句并生成 Python SQLAlchemy 模型代碼&#xff0c;適用于數據庫管理、后端開發和 ORM 結構映射。無需手寫 SQLAlchemy 模型&#xff0c;一鍵轉換 SQL 結構&#xff0c;提升開發效率&#xff0c;簡化數據庫…

自定義tiptap插件

本文為開發開源項目的真實開發經歷&#xff0c;感興趣的可以來給我的項目點個star&#xff0c;謝謝啦~ 具體博文介紹&#xff1a; 開源&#xff5c;Documind協同文檔&#xff08;接入deepseek-r1、支持實時聊天&#xff09;Documind &#x1f680; 一個支持實時聊天和接入 - 掘…