?系列總鏈接:《大話設計模式》學習記錄_net 大話設計-CSDN博客
1.概述
? ? ?中介者模式(Mediator Pattern)是一種行為設計模式,旨在通過一個中介對象來封裝一系列對象之間的交互方式,從而減少這些對象間的直接依賴。在該模式下,各個組件(同事)不再直接相互通信,而是通過中介者進行間接溝通,這極大地降低了系統的耦合度。具體來說,中介者定義了同事類之間的通信接口,并負責協調同事對象之間的交互邏輯。每個同事類都知道其對應的中介者對象,但并不直接與其他同事類交互。
2.結構與實現
結構:
- Mediator(抽象中介者):定義同事類之間的通信接口。
- ConcreteMediator(具體中介者):實現了抽象中介者的接口,并協調各同事對象之間的交互。
- Colleague Class(抽象同事類):每個同事類都知道其對應的中介者對象,并且可以通過中介者發送消息給其他同事。
- ConcreteColleague(具體同事類):實現了抽象同事類,負責發送和接收消息。
實現:
假設我們要創建一個簡單的聊天應用程序,用戶之間通過ChatRoom(中介者)進行交流。
代碼目錄結構為:
首先,定義ChatRoom
作為抽象中介者:
ChatRoom.h:
#ifndef CHATROOM_H
#define CHATROOM_H#include <QString>class User; // 前向聲明User類,避免循環依賴// 抽象中介者:定義同事類之間的通信接口。
class ChatRoom {
public:virtual void sendMessage(const QString& message, User* user) = 0; // 發送消息的純虛函數
};#endif // CHATROOM_H
ConcreteChatRoom.h
#ifndef CONCRETECHATROOM_H
#define CONCRETECHATROOM_H#include "ChatRoom.h"
#include <QList> // Qt容器類,用于存儲用戶列表
#include "User.h"// 具體中介者:實現了抽象中介者的接口,并協調各同事對象之間的交互。
class ConcreteChatRoom : public ChatRoom {
private:QList<User*> users; // 存儲所有用戶的列表
public:// 添加用戶到聊天室中void addUser(User* user) {users.append(user);}// 實現發送消息的功能void sendMessage(const QString& message, User* user) override;
};#endif // CONCRETECHATROOM_H
ConcreteChatRoom.cpp
#include "ConcreteChatRoom.h"
#include "User.h"
#include <QDebug>// 實現sendMessage方法,遍歷所有用戶并轉發消息給其他用戶(除了發送者)
void ConcreteChatRoom::sendMessage(const QString& message, User* user)
{// 遍歷所有用戶for (User* u : users){if(u != user) { // 如果不是消息的發送者,則轉發消息u->receiveMessage(message); // 調用接收消息的方法}}
}
User.h
#ifndef USER_H
#define USER_H#include <QString>
#include "ChatRoom.h" // 包含中介者接口// 抽象同事類:每個同事類都知道其對應的中介者對象,并且可以通過中介者發送消息給其他同事。
class User {
protected:ChatRoom* chatroom; // 指向中介者的指針QString name; // 用戶名
public:// 構造函數,初始化中介者和用戶名User(ChatRoom* chatroom, const QString& name): chatroom(chatroom), name(name) {}// 發送消息的方法virtual void sendMessage(const QString& message);// 接收消息的方法virtual void receiveMessage(const QString& message);// 獲取用戶名的方法QString getName() const { return name; }
};#endif // USER_H
User.cpp
#include "User.h"
#include "ConcreteChatRoom.h" // 包含具體中介者的頭文件
#include <QDebug>// 發送消息的實現
void User::sendMessage(const QString& message) {qDebug() << getName() << " sends: " << message; // 打印發送者信息chatroom->sendMessage(message, this); // 通過中介者發送消息
}// 接收消息的實現
void User::receiveMessage(const QString& message) {qDebug() << getName() << " receives: " << message; // 打印接收者信息
}
main.cpp:
#include <QCoreApplication>
#include "ConcreteChatRoom.h" // 包含具體中介者
#include "User.h" // 包含同事類int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 創建一個具體的中介者實例ConcreteChatRoom chatRoom;// 創建兩個用戶并關聯到同一個中介者User user1(&chatRoom, "Alice");User user2(&chatRoom, "Bob");User user3(&chatRoom, "Tom");// 將用戶添加到聊天室中chatRoom.addUser(&user1);chatRoom.addUser(&user2);chatRoom.addUser(&user3);// 用戶發送消息user1.sendMessage("Hello Bob!");//user2.sendMessage("Hi Alice!");return a.exec();
}
運行效果:
"Alice" sends: "Hello Bob!"
"Bob" receives: "Hello Bob!"
"Tom" receives: "Hello Bob!"
3.應用
中介者模式非常適合用于以下場景:
- GUI框架中,例如Qt,其中各種控件可能需要相互通訊但又不希望直接依賴對方。
- 多模塊或分布式系統中,各個模塊或節點之間的通信可以由中介者集中管理。
- 狀態管理器或控制器層,用于管理不同視圖組件的狀態更新和事件分發。
4.優缺點及適用環境
優點:
- 減少依賴:減少了同事對象之間的直接依賴,降低了系統的耦合度。
- 簡化交互:通過中介者集中管理對象間的交互,使得代碼更加清晰易讀。
- 易于擴展:新增同事對象時不需要修改現有的同事對象,只需調整中介者即可。
缺點:
- 復雜性增加:如果中介者變得過于復雜,可能會成為系統的瓶頸,同時也會增加維護成本。
- 單一職責原則:如果中介者承擔過多的責任,可能會導致其變得龐大且難以管理。
應用環境:
- 當系統中有大量對象需要相互通信,但你希望避免它們之間的直接引用時。
- 對于那些希望通過引入中介者來提高模塊獨立性的系統來說,中介者模式是一個很好的選擇。
- 在開發復雜的GUI應用程序時,使用中介者模式可以幫助更好地管理和控制組件之間的交互。
? ? ? 通過職責鏈模式,我們可以構建更加靈活、易于擴展的應用程序,尤其是在涉及多種類型的請求處理時。然而,在使用此模式時也應注意其可能帶來的性能損耗和復雜性的增加。
5.舉一反三
中介者模式因其能有效減少對象間的直接依賴和簡化復雜的交互邏輯,適用于多種場景。以下是一些可以應用中介者模式的具體例子及其應用場景:
1. GUI應用程序
在Qt或其他GUI框架中,組件(如按鈕、文本框等)之間的交互往往比較復雜。使用中介者模式可以幫助管理這些交互,避免組件間直接相互引用。
- 示例:在一個表單中,某些輸入框的可用性可能取決于其他輸入框的內容或狀態。例如,選擇“是否需要發票”復選框后,相關的稅號輸入框才變為可編輯狀態。通過引入一個中介者來監聽這些事件并更新相應的UI組件狀態,可以使代碼更加清晰且易于維護。
2. 分布式系統中的模塊通信
在分布式系統或微服務架構中,各個服務或模塊之間需要進行通信。為了避免服務之間的直接依賴,可以通過引入中介者(如消息隊列或API網關)來解耦這些服務。
- 示例:在一個電商系統中,訂單服務、庫存服務和支付服務都需要相互通信以完成下單流程。使用中介者模式可以確保這些服務不直接相互調用,而是通過中介者傳遞消息,從而提高了系統的靈活性和可擴展性。
3. 游戲開發中的物體交互
在游戲中,不同游戲物體(如角色、敵人、道具等)之間的交互非常頻繁。使用中介者模式可以幫助管理這些交互,特別是當涉及到多個物體同時對同一事件作出反應時。
- 示例:在一個多人在線游戲中,當玩家撿起一件裝備時,不僅該玩家的狀態會發生變化,其他玩家也可能看到這一變化。通過引入一個中介者來協調這些狀態更新,可以有效地管理復雜的同步邏輯。
4. 狀態管理和事件分發
在具有復雜狀態的應用程序中,比如企業級應用或大型網站,狀態的變化可能會影響到多個視圖或組件。使用中介者模式可以幫助集中管理這些狀態變化,并通知相關聯的視圖或組件進行更新。
- 示例:在一個具有多個視圖的單頁應用(SPA)中,用戶登錄狀態的變化可能會影響導航欄、側邊欄等多個地方。通過使用中介者來處理這種狀態變化,并向所有相關視圖廣播通知,可以使狀態管理更加簡潔高效。
5. 智能家居控制系統
智能家居設備(如燈光、溫度控制器、安全系統等)通常需要根據環境變化或其他設備的狀態自動調整其行為。使用中介者模式可以使得這些設備之間的交互更加靈活和獨立。
- 示例:當智能門鎖檢測到有人進入房屋時,它可以通過中介者通知室內照明系統開啟特定區域的燈光,并告知溫控器調整室溫。這種方式既實現了設備間的解耦,又保證了響應的及時性和準確性。
總之,中介者模式非常適合用于那些需要管理多個對象間復雜交互的場景,特別是在希望減少對象間直接依賴、提高模塊獨立性以及簡化交互邏輯的情況下。通過合理地應用中介者模式,可以構建出更加靈活、易于維護和擴展的軟件系統。