深入理解設計模式之中介者模式:解耦對象交互的利器

為什么需要中介者?

在軟件開發中,我們經常會遇到對象之間需要相互通信的場景。當系統規模較小時,對象直接相互引用并通信可能不會帶來太大問題。但隨著系統復雜度增加,對象間的交互關系會變得錯綜復雜,形成一個復雜的網狀結構。這種高度耦合的設計會導致以下問題:

  1. 可維護性差:牽一發而動全身,修改一個對象可能需要修改多個相關對象

  2. 復用性低:由于對象間高度依賴,很難單獨復用某個對象

  3. 擴展困難:新增或修改交互邏輯需要改動大量現有代碼

中介者模式正是為解決這些問題而生的。它通過引入一個中介對象來封裝對象間的交互,使對象間不再直接引用,而是通過中介者進行間接通信,從而將網狀結構轉化為星型結構,大大降低了系統的耦合度。

中介者模式的核心概念

模式定義

中介者模式(Mediator Pattern)的定義是:用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。

模式結構

中介者模式包含四個關鍵角色:

  1. Mediator(中介者接口)

    • 定義同事對象到中介者對象的接口

    • 通常包含一個或多個事件處理方法

  2. ConcreteMediator(具體中介者)

    • 實現中介者接口

    • 協調各同事對象的行為

    • 知道并維護它的各個同事

  3. Colleague(同事類接口)

    • 定義同事類的接口

    • 通常持有中介者的引用

  4. ConcreteColleague(具體同事類)

    • 實現同事類接口

    • 每個具體同事類只知道自己的行為

    • 需要與其他同事通信時,通過中介者轉發

UML類圖

┌─────────────┐       ┌─────────────┐
│   Mediator  │<------│  Colleague  │
└─────────────┘       └─────────────┘^                      ^|                      |
┌─────────────┐       ┌─────────────┐
│ConcreteMedi │       │ConcreteColl │
└─────────────┘       └─────────────┘

深入解析中介者模式

工作原理

  1. 對象注冊:同事對象在創建時向中介者注冊自己

  2. 通信機制:當同事對象需要與其他同事通信時,不是直接調用對方的方法,而是通知中介者

  3. 消息轉發:中介者接收到消息后,根據業務邏輯決定如何轉發給其他同事對象

  4. 解耦實現:同事對象之間不再相互持有引用,所有交互都通過中介者進行

代碼實現詳解

讓我們通過一個完整的聊天室示例來深入理解中介者模式的實現:

// 1. 定義中介者接口
public interface ChatMediator {void sendMessage(String msg, User user);void addUser(User user);
}// 2. 實現具體中介者
public class ChatMediatorImpl implements ChatMediator {private List<User> users;public ChatMediatorImpl() {this.users = new ArrayList<>();}@Overridepublic void sendMessage(String msg, User user) {for (User u : this.users) {// 消息不發送給發送者自己if (u != user) {u.receive(msg);}}}@Overridepublic void addUser(User user) {this.users.add(user);}
}// 3. 定義同事類(用戶)抽象
public abstract class User {protected ChatMediator mediator;protected String name;public User(ChatMediator med, String name) {this.mediator = med;this.name = name;}public abstract void send(String msg);public abstract void receive(String msg);
}// 4. 實現具體同事類
public class UserImpl extends User {public UserImpl(ChatMediator med, String name) {super(med, name);}@Overridepublic void send(String msg) {System.out.println(this.name + " 發送消息: " + msg);mediator.sendMessage(msg, this);}@Overridepublic void receive(String msg) {System.out.println(this.name + " 收到消息: " + msg);}
}// 5. 客戶端使用
public class ChatClient {public static void main(String[] args) {ChatMediator mediator = new ChatMediatorImpl();User user1 = new UserImpl(mediator, "張三");User user2 = new UserImpl(mediator, "李四");User user3 = new UserImpl(mediator, "王五");mediator.addUser(user1);mediator.addUser(user2);mediator.addUser(user3);user1.send("大家好!");user2.send("歡迎新人!");}
}

輸出結果

張三 發送消息: 大家好!
李四 收到消息: 大家好!
王五 收到消息: 大家好!
李四 發送消息: 歡迎新人!
張三 收到消息: 歡迎新人!
王五 收到消息: 歡迎新人!

中介者模式的優缺點

優點

  1. 降低耦合度:將對象間多對多的關系轉化為一對多的關系,減少對象間的直接依賴

  2. 集中控制:將交互邏輯集中在中介者中,使交互行為更容易理解和維護

  3. 簡化對象協議:用中介者和同事間的一對多交互替代了同事之間的多對多交互

  4. 提高靈活性:可以獨立地改變和復用各個同事類和中介者類

  5. 減少子類生成:將原本分布于多個對象間的行為集中在一起,減少子類的生成

缺點

  1. 中介者可能變得復雜:隨著交互邏輯的增加,中介者可能變得過于龐大和復雜

  2. 性能考慮:所有通信都通過中介者轉發,可能帶來一定的性能開銷

  3. 單點故障風險:中介者成為系統的關鍵點,一旦出現問題會影響整個系統

中介者模式的應用場景

中介者模式特別適用于以下場景:

  1. GUI開發:各種UI組件(按鈕、文本框等)之間的交互

  2. 聊天應用:多個用戶之間的消息傳遞

  3. 航空管制系統:飛機與塔臺之間的通信協調

  4. 事件分發系統:多個對象需要響應同一事件

  5. 工作流引擎:協調多個處理節點之間的交互

  6. 游戲開發:游戲對象之間的交互管理

實際應用案例

案例1:機場塔臺控制系統

在航空領域,飛機之間的通信不是直接進行的,而是通過塔臺這個中介者來協調:

// 中介者:塔臺
public interface Tower {void registerFlight(Flight flight);void sendWarning(String message, Flight sender);
}// 具體同事:飛機
public abstract class Flight {protected Tower tower;protected String flightNumber;public Flight(Tower tower, String flightNumber) {this.tower = tower;this.flightNumber = flightNumber;tower.registerFlight(this);}public abstract void receiveWarning(String message);public abstract void sendWarning(String message);
}// 使用示例
public class AviationExample {public static void main(String[] args) {Tower tower = new ControlTower();Flight flight1 = new CommercialFlight(tower, "CA123");Flight flight2 = new CargoFlight(tower, "FX456");flight1.sendWarning("前方有氣流,請注意");flight2.sendWarning("收到,正在調整高度");}
}

案例2:電子商務訂單系統

在電商系統中,訂單處理涉及多個組件(庫存、支付、物流等),可以使用中介者協調:

public interface OrderMediator {void placeOrder(Order order);void cancelOrder(Order order);void processPayment(Order order);void updateInventory(Order order);void arrangeShipping(Order order);
}public class OrderProcessor implements OrderMediator {// 實現各種訂單處理邏輯// 協調庫存、支付、物流等子系統
}// 同事類:支付系統
public class PaymentSystem {private OrderMediator mediator;public void processPayment(Order order) {// 處理支付mediator.updateInventory(order);}
}

中介者模式與其他模式的關系

  1. 與外觀模式

    • 相似點:都抽象了已有類的功能

    • 區別:外觀模式是單向的,為子系統提供統一接口;中介者模式是雙向的,協調多個對象間的交互

  2. 與觀察者模式

    • 可以組合使用,中介者通常使用觀察者模式來實現同事對象之間的通信

    • 觀察者模式側重一對多的依賴關系,中介者模式側重對象間的交互解耦

  3. 與命令模式

    • 命令模式可用于實現中介者與同事之間的通信機制

  4. 與代理模式

    • 代理模式控制對一個對象的訪問,而中介者模式控制多個對象間的交互

最佳實踐與注意事項

  1. 避免過度使用:不要為了使用模式而使用模式,只有對象間交互確實復雜時才考慮中介者

  2. 保持中介者簡潔:不要讓中介者承擔太多職責,必要時可以拆分多個中介者

  3. 合理設計接口:中介者接口應該足夠抽象,不應依賴于具體同事類

  4. 性能優化:對于高頻交互的場景,考慮引入緩存或批處理機制

  5. 異常處理:中介者應該妥善處理同事對象拋出的異常,避免影響整個系統

總結

中介者模式是一種強大的設計模式,它通過引入中介對象來解耦對象間的復雜交互。在適當的場景下使用中介者模式可以帶來以下好處:

  • 使系統結構更加清晰

  • 降低組件間的耦合度

  • 提高代碼的可維護性和可擴展性

  • 使交互邏輯更加集中和明確

然而,中介者模式也不是萬能的。當交互邏輯簡單時,使用中介者可能會引入不必要的復雜性。因此,作為開發者,我們需要根據實際場景權衡利弊,做出最合適的設計決策。

?

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

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

相關文章

從 0 安裝 Label Studio:搭建可后臺運行的數據標注平臺(systemd 實踐

本文將介紹如何使用 pip 安裝 Label Studio&#xff0c;并通過 systemd 實現開機自啟與后臺運行&#xff0c;適用搭建個人項目的數據標注平臺。 一、Label Studio 簡介 Label Studio 是一個開源、跨模態的數據標注工具&#xff0c;支持文本、圖像、音頻、視頻、HTML等多種類型…

【數據結構】鏈表(linked list)

目錄 一、鏈表的介紹 二、單鏈表 1. 單鏈表的初始化 2. 單鏈表的插入 &#xff08;1&#xff09;動態申請一個節點 &#xff08;2&#xff09;頭插法 &#xff08;3&#xff09;尾插法 &#xff08;4&#xff09;按照位置來插入 &#xff08;5&#xff09;在地址之前插…

反序列化漏洞1-PHP序列化基礎概念(0基礎超詳細)

一.PHP序列化基礎概念首先當我們看到反序列化漏洞這個概念&#xff0c;我們的第一個問題是什么是反序列化&#xff1f;那么我們要知道什么是反序列化就要知道什么是序列化。序列化就是可以將一個對象壓縮并格式化成字符串&#xff0c;可以將該對象保存下來&#xff0c;以便存儲…

【微服務】Ocelot微服務網關

目錄 一、目的 二、Ocelot介紹 三、.Net中使用Ocelot搭建網關服務 3.1 搭建網關Ocelot步驟 3.1.1、創建Net7 WebApi服務 3.1.2、Nuget引入-Ocelot程序包&#xff08;版本&#xff1a;19.0.2&#xff09; 3.1.3、配置中間件和IOC注冊 3.1.4 配置文件編輯Ocelot網關配置信…

零基礎入門:用按鍵精靈實現視頻自動操作(附完整腳本)

摘要&#xff1a;本文手把手教你編寫視頻平臺的自動化腳本&#xff0c;涵蓋點擊、循環、防檢測等核心技巧&#xff0c;無需編程基礎&#xff0c;輕松實現自動播放/點贊/跳過廣告。&#xff08;使用按鍵精靈2024版演示&#xff09; 一、應用場景 自動化操作&#xff1a;自動跳過…

AI(學習筆記第六課) 使用langchain進行AI開發 load documents(csv和文件夾)

文章目錄AI(學習筆記第六課) 使用langchain進行AI開發 load documents(csv和文件夾)學習內容&#xff1a;1.load documents&#xff08;csv&#xff09;1.1 學習url1.2 load csv文件1.2.1 默認load1.2.2 csv文件內容1.2.2 執行csv文件的load1.3 Customizing the CSV parsing an…

企業運維實戰:Jenkins 依賴 JDK21 與應用需 JDK1.8 共存方案(含流水線配置)

前言&#xff1a;在企業運維中&#xff0c;“工具升級”與“業務兼容”的平衡始終是核心挑戰。近期我們遇到一個典型場景&#xff1a;Jenkins 升級到 2.450 版本后&#xff0c;強制要求 JDK21 運行環境&#xff1b;但開發團隊的應用程序因框架依賴&#xff0c;必須使用 JDK1.8 …

爬蟲小知識三:selenium庫

前言 selenium 庫是一種用于 Web 應用程序測試的工具&#xff0c;它可以驅動瀏覽器執行特定操作&#xff0c;自動按照腳本代碼做出單擊、輸入、打開、驗證等操作&#xff0c;支持的瀏覽器包括 IE、Firefox、Safari、Chrome、Opera 等。 與 requests 庫不同的是&#xff0c;se…

Jmeter使用 -1

1 接口測試1.1 為什么要進行接口測試接口測試能夠繞過前端校驗&#xff0c;對后端的接口處理邏輯進行測試&#xff08;數據的邊界/格式/類型&#xff09;在一些需要重復測試的需求中&#xff0c;接口自動化的效率比手工執行效率高1.2 接口測試流程熟悉API接口文檔&#xff08;接…

GitHub 趨勢日報 (2025年07月16日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖2415markitdown570claude-code434ART330erpnext150MusicFree146rustdesk129vanna80…

Python+Tkinter制作音頻格式轉換器

我們將使用Python的Tkinter庫來構建一個音頻格式轉換器界面。由于音頻轉換需要實際的處理&#xff0c;我們將使用pydub庫&#xff08;需要安裝&#xff09;來進行音頻格式轉換。同時&#xff0c;我們會使用ffmpeg作為后端&#xff0c;因此請確保系統中已安裝ffmpeg并添加到環境…

Haproxy算法精簡化理解及企業級高功能實戰

文章目錄4. Haproxy的算法4.1 靜態算法4.1.1 static-rr&#xff1a;基于權重的輪詢調度1. 示例&#xff1a;4.1.2 first1. 示例2. 測試效果&#xff1a;4.2 動態算法4.2.1 roundrobin1. 示例2. 動態調整權重4.2.2 leastconn1. 示例4.3 其他算法4.3.1 source1. 示例2. 測試4.3.2…

git fork的項目遠端標準協作流程 倉庫設置[設置成upstream]

這是一個在開源協作中非常常見的配置。 簡單來說&#xff0c;upstream 在這里指的是你 Fork 來的那個原始的、官方的倉庫。 下面我們來詳細解釋一下這個 git remote -v 輸出的含義&#xff1a; 1. 兩條“遙控器” (Remotes) 你的 git 配置了兩個遠程倉庫的地址&#xff0c;就像…

[FFmpeg] 輸入輸出訪問 | 管道系統 | AVIOContext 與 URLProtocol | 門面模式

鏈接&#xff1a;https://trac.ffmpeg.org/ docs&#xff1a;FFmpeg FFmpeg 是一個強大的多媒體框架&#xff0c;旨在處理媒體處理的各個階段。 它就像一個數字媒體工廠&#xff0c;包含以下部門&#xff1a;打包/解包&#xff08;容器處理&#xff09;、 轉譯/壓縮&#xff…

微服務的編程測評系統2

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄前言工程創建創建ck-oj創建oj-modules創建具體微服務oj-system推送碼云管理員登錄邏輯分析docker安裝mysqldocker客戶端docker desktop安裝安裝mysqlmysql-plus和數據…

AR智能巡檢:電力運維的數字化變革

在電力行業快速發展的當下&#xff0c;傳統運維方式已難以滿足現代電網對高效、安全的需求。近年來&#xff0c;增強現實&#xff08;AR www.teamhelper.cn &#xff09;技術的興起為電力巡檢帶來了全新的解決方案。通過實時數據可視化、遠程協作和智能分析&#xff0c;AR技術…

NeRF和3DGS原理詳細

NeRF和3DGS一、傳統三維表征方法1.1 顯示表征1.2 隱式表征二、NeRF&#xff08;Nerual Radiance Field&#xff09;2.1 NeRF場景表示2.2 NeRF訓練流程2.3 NeRF體渲染2.4 NeRF位置編碼2.5 NeRF體素分層采樣&#xff08;Volume Hierarchical Sampling&#xff09;2.6 NeRF網絡結構…

035_ClaudeCode_MCP_介紹

035_ClaudeCode_MCP_介紹 摘要 Model Context Protocol&#xff08;MCP&#xff09;是一個開放的標準化協議&#xff0c;專為大型語言模型提供上下文數據而設計。作為Claude Code生態系統的重要組成部分&#xff0c;MCP如同"AI應用程序的USB-C端口"&#xff0c;提供…

Python 程序無法找到 Oracle 的 64 位客戶端庫 (libclntsh.so)

數據庫錯誤: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help 這個錯誤表明 Python 程序無法找到…

Kubernetes常用命令總結

文章目錄Kubernetes常用命令總結1. 集群管理命令kubectl cluster-infokubectl get nodeskubectl describe node <node-name>kubectl top nodes2. Pod相關命令kubectl get podskubectl get pods -o widekubectl describe pod <pod-name>kubectl logs <pod-name&g…