中介者模式及优化
中介者模式(Mediator Pattern)是一种行为型设计模式,其核心思想是通过引入一个“中介者”对象,封装多个对象(称为“同事对象”)之间的复杂交互关系,使同事对象无需直接相互引用,而是通过中介者间接通信。这种模式本质上是**“迪米特法则”(最少知识原则)** 的极致体现,旨在解耦对象间的网状依赖,将多对多关系转化为中介者与同事对象之间的一对多关系。
一、介绍
核心角色
- 抽象中介者(Mediator): 定义中介者与同事对象交互的接口,通常包含“注册同事”和“转发请求”的抽象方法。
- 具体中介者(ConcreteMediator): |实现抽象中介者接口,维护所有同事对象的引用,协调同事对象的交互逻辑。
- 抽象同事(Colleague): 定义同事对象的公共接口,持有抽象中介者的引用,确保同事能通过中介者通信。
- 具体同事(ConcreteColleague): |实现抽象同事接口,自身业务逻辑与中介者交互(而非直接与其他同事交互)。
优点
- 降低耦合度
- 将多对多的对象关系转化为一对多的关系,减少对象间的直接依赖
- 每个对象只需关注自身业务逻辑,无需了解其他对象的具体实现
- 集中控制交互
- 所有对象间的交互逻辑集中在中介者中,便于理解和维护
- 变更交互规则时,只需修改中介者,无需修改各个对象
- 简化对象协议
- 对象间无需制定复杂的交互协议,只需与中介者通信
- 新对象加入系统时,只需与中介者交互即可,无需修改现有对象
- 提高可扩展性
- 新增对象时,只需在中介者中添加相应的处理逻辑
- 可以通过扩展中介者来实现新的交互规则
- 符合迪米特法则
- 每个对象只需要了解中介者,不需要了解其他对象
- 减少了对象之间的通信开销和复杂度
适用场景
- 多个对象之间存在复杂交互关系
- 当系统中对象数量较多,且对象之间存在多对多的交互关系,形成复杂的网络结构时
- 例如:聊天室中用户之间的消息传递、游戏中多个角色之间的互动
- 需要简化对象间通信
- 当对象间的直接引用导致系统难以理解和维护时
- 例如:GUI界面中多个控件(按钮、文本框、列表等)之间的联动
- 需要集中管理对象交互逻辑
- 当对象间的交互规则复杂,且可能频繁变化时
- 例如:电商平台中订单、库存、支付、物流等模块之间的协作
- 需要减少对象间的耦合度
- 当希望提高系统的可复用性和可扩展性时
- 例如:微服务架构中的服务协调器、分布式系统中的中间件
二、实现
以聊天室系统为例,展示如何使用中介者模式管理用户之间的消息交互
#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>
#include <chrono>
#include <iomanip>
#include <sstream>// 前向声明
class User;// 抽象中介者:聊天室接口
class ChatRoomMediator {
public:virtual ~ChatRoomMediator() = default;// 注册用户virtual void registerUser(std::shared_ptr<User> user) = 0;// 发送消息virtual void sendMessage(const std::string& senderId, const std::string& receiverId, const std::string& message) = 0;// 广播消息virtual void broadcastMessage(const std::string& senderId, const std::string& message) = 0;// 获取在线用户列表virtual std::vector<std::string> getOnlineUsers() const = 0;
};// 抽象同事:用户接口
class User {
protected:ChatRoomMediator* mediator_; // 中介者引用std::string userId_; // 用户IDstd::string userName_; // 用户名public:User(ChatRoomMediator* mediator, std::string userId, std::string userName): mediator_(mediator), userId_(std::move(userId)), userName_(std::move(userName)) {if (!mediator_) {throw std::invalid_argument("中介者对象不能为空");}}virtual ~User() = default;// 发送消息给指定用户void sendTo(const std::string& receiverId, const std::string& message) {mediator_->sendMessage(userId_, receiverId, message);}// 广播消息给所有用户void broadcast(const std::string& message) {mediator_->broadcastMessage(userId_, message);}// 获取在线用户列表std::vector<std::string> getOnlineUsers() const {return mediator_->getOnlineUsers();}// 接收消息(由子类实现)virtual void receive(const std::string& senderName, const std::string& message, const std::string& timestamp) = 0;// 获取用户IDconst std::string& getUserId() const { return userId_; }// 获取用户名const std::string& getUserName() const { return userName_; }
};// 具体同事:普通用户
class RegularUser : public User {
public:RegularUser(ChatRoomMediator* mediator, std::string userId, std::string userName): User(mediator, std::move(userId), std::move(userName)) {}void receive(const std::string& senderName, const std::string& message, const std::string& timestamp) override {std::cout << "[" << timestamp << "] " << userName_ << " 收到来自 " << senderName << " 的消息: " << message << std::endl;}
};// 具体同事:VIP用户
class VIPUser : public User {
private:bool notificationsEnabled_ = true; // 是否启用消息通知public:VIPUser(ChatRoomMediator* mediator, std::string userId, std::string userName): User(mediator, std::move(userId), std::move(userName)) {}void receive(const std::string& senderName, const std::string& message, const std::string& timestamp) override {if (notificationsEnabled_) {std::cout << "[" << timestamp << "] [VIP] " << userName_ << " 收到来自 " << senderName << " 的消息: " << message << std::endl;} else {std::cout << "[" << timestamp << "] [VIP] " << userName_ << " 的消息已静音: " << message << std::endl;}}// 启用/禁用消息通知void setNotificationsEnabled(bool enabled) {notificationsEnabled_ = enabled;std::cout << userName_ << " 的消息通知已" << (enabled ? "启用" : "禁用") << std::endl;}
};// 具体中介者:聊天室
class ChatRoom : public ChatRoomMediator {
private:std::unordered_map<std::string, std::shared_ptr<User>> users_; // 用户映射表std::string roomName_; // 聊天室名称// 获取当前时间戳std::string getCurrentTimestamp() const {auto now = std::chrono::system_clock::now();auto time = std::chrono::system_clock::to_time_t(now);auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch() % std::chrono::seconds(1));std::stringstream ss;ss << std::put_time(std::localtime(&time), "%H:%M:%S") << "." << std::setw(3) << std::setfill('0') << ms.count();return ss.str();}public:explicit ChatRoom(std::string roomName) : roomName_(std::move(roomName)) {std::cout << "聊天室 '" << roomName_ << "' 创建成功" << std::endl;}// 注册用户void registerUser(std::shared_ptr<User> user) override {if (!user) {throw std::invalid_argument("用户对象不能为空");}const std::string& userId = user->getUserId();if (users_.find(userId) != users_.end()) {std::cout << "用户 " << user->getUserName() << " 已在聊天室中" << std::endl;return;}users_[userId] = user;broadcastMessage("", user->getUserName() + " 加入了聊天室");std::cout << "用户 " << user->getUserName() << " 已加入聊天室" << std::endl;}// 发送消息给指定用户void sendMessage(const std::string& senderId, const std::string& receiverId, const std::string& message) override {auto senderIt = users_.find(senderId);auto receiverIt = users_.find(receiverId);if (senderIt == users_.end()) {std::cout << "错误: 发送者不存在" << std::endl;return;}if (receiverIt == users_.end()) {std::cout << "错误: 接收者 " << receiverId << " 不存在或未加入聊天室" << std::endl;return;}std::string timestamp = getCurrentTimestamp();receiverIt->second->receive(senderIt->second->getUserName(), message, timestamp);}// 广播消息给所有用户void broadcastMessage(const std::string& senderId, const std::string& message) override {std::string timestamp = getCurrentTimestamp();std::string senderName = senderId.empty() ? "系统" : users_.at(senderId)->getUserName();for (const auto& pair : users_) {// 不发送给发送者自己if (pair.first != senderId) {pair.second->receive(senderName, message, timestamp);}}}// 获取在线用户列表std::vector<std::string> getOnlineUsers() const override {std::vector<std::string> userNames;for (const auto& pair : users_) {userNames.push_back(pair.second->getUserName());}return userNames;}// 移除用户void removeUser(const std::string& userId) {auto it = users_.find(userId);if (it != users_.end()) {std::string userName = it->second->getUserName();users_.erase(it);broadcastMessage("", userName + " 离开了聊天室");std::cout << "用户 " << userName << " 已离开聊天室" << std::endl;}}// 获取聊天室名称const std::string& getRoomName() const {return roomName_;}
};// 客户端代码
int main() {try {// 创建聊天室(中介者)ChatRoom chatRoom("设计模式讨论群");// 创建用户(同事)auto alice = std::make_shared<RegularUser>(&chatRoom, "U001", "Alice");auto bob = std::make_shared<VIPUser>(&chatRoom, "U002", "Bob");auto charlie = std::make_shared<RegularUser>(&chatRoom, "U003", "Charlie");// 用户加入聊天室chatRoom.registerUser(alice);chatRoom.registerUser(bob);chatRoom.registerUser(charlie);// 显示在线用户std::cout << "\n当前在线用户: ";for (const auto& name : alice->getOnlineUsers()) {std::cout << name << " ";}std::cout << std::endl;// 发送消息std::cout << "\n--- 开始聊天 ---" << std::endl;alice->sendTo("U002", "你好 Bob,中介者模式怎么理解?");bob->sendTo("U001", "中介者模式主要是用来解耦多个对象之间的交互");charlie->broadcast("我认为中介者模式类似于现实中的经纪人");// Bob 禁用消息通知std::dynamic_pointer_cast<VIPUser>(bob)->setNotificationsEnabled(false);alice->sendTo("U002", "Bob,你能再详细解释一下吗?");// Bob 离开聊天室chatRoom.removeUser("U002");// 继续聊天std::cout << "\n--- 继续聊天 ---" << std::endl;alice->sendTo("U003", "Charlie,你用过中介者模式吗?");charlie->sendTo("U001", "用过,在设计聊天系统时特别有用");} catch (const std::exception& e) {std::cerr << "发生错误: " << e.what() << std::endl;return 1;}return 0;
}
输出结果(示例)
聊天室 '设计模式讨论群' 创建成功
[10:30:45.123] 系统 收到来自 的消息: Alice 加入了聊天室
用户 Alice 已加入聊天室
[10:30:45.125] Alice 收到来自 系统 的消息: Bob 加入了聊天室
[10:30:45.125] [VIP] Bob 收到来自 系统 的消息: Bob 加入了聊天室
用户 Bob 已加入聊天室
[10:30:45.126] Alice 收到来自 系统 的消息: Charlie 加入了聊天室
[10:30:45.126] [VIP] Bob 收到来自 系统 的消息: Charlie 加入了聊天室
用户 Charlie 已加入聊天室当前在线用户: Alice Bob Charlie --- 开始聊天 ---
[10:30:45.126] [VIP] Bob 收到来自 Alice 的消息: 你好 Bob,中介者模式怎么理解?
[10:30:45.126] Alice 收到来自 Bob 的消息: 中介者模式主要是用来解耦多个对象之间的交互
[10:30:45.126] Alice 收到来自 Charlie 的消息: 我认为中介者模式类似于现实中的经纪人
[10:30:45.126] [VIP] Bob 收到来自 Charlie 的消息: 我认为中介者模式类似于现实中的经纪人
Bob 的消息通知已禁用
[10:30:45.126] [VIP] Bob 的消息已静音: Bob,你能再详细解释一下吗?
[10:30:45.126] Alice 收到来自 系统 的消息: Bob 离开了聊天室
[10:30:45.126] Charlie 收到来自 系统 的消息: Bob 离开了聊天室
用户 Bob 已离开聊天室--- 继续聊天 ---
[10:30:45.126] Charlie 收到来自 Alice 的消息: Charlie,你用过中介者模式吗?
[10:30:45.126] Alice 收到来自 Charlie 的消息: 用过,在设计聊天系统时特别有用
应用场景
- 通信系统
- 聊天室、即时通讯软件中的消息转发机制
- 电话交换机、路由器等网络设备
- GUI框架
- 窗口管理器协调多个控件之间的交互
- 如Qt中的QWidget和信号槽机制
- 游戏开发
- 游戏世界管理器协调玩家、NPC、物品之间的交互
- 碰撞检测系统处理游戏对象之间的碰撞关系
- 企业应用
- 工作流引擎协调各个业务节点的执行顺序
- 订单处理系统协调库存、支付、物流等模块
- 分布式系统
- 服务注册中心协调微服务之间的通信
- 消息队列中间件(如RabbitMQ、Kafka)作为中介者转发消息
三、优化
优化点
- 引入消息类型与结构
- 定义
Message
结构体封装消息内容、发送者、接收者、时间戳等元数据 - 增加
MessageType
枚举区分不同类型消息(文本、系统、通知等) - 支持消息附加信息(metadata),增强扩展性
- 定义
- 添加消息过滤机制
- 引入
MessageFilter
接口,实现关键词过滤、长度限制等功能 - 支持动态添加过滤器,无需修改核心逻辑
- 不同用户类型可应用不同过滤规则(如管理员不受长度限制)
- 引入
- 丰富用户类型与权限
- 扩展用户类型:普通用户、VIP用户、管理员
- 为不同用户添加专属功能:VIP的免打扰模式、管理员的踢人功能
- 实现用户屏蔽功能,增强交互控制
- 增强中介者功能
- 添加消息历史记录,便于追踪和回溯
- 完善用户管理(注册/移除/查询)
- 支持聊天室信息展示,提高系统透明度
- 提高代码可扩展性
- 采用接口和抽象类设计,便于新增用户类型和过滤器
- 使用组合而非继承扩展功能,符合开闭原则
- 松耦合设计使新增功能(如文件传输、表情系统)更容易实现
- 增强错误处理与健壮性
- 添加参数验证和异常处理
- 处理边界情况(如发送给不存在的用户、自己踢自己等)
- 完善状态检查,避免空指针等常见错误
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <vector>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <functional>
#include <stdexcept>// 前向声明
class User;
class ChatRoomMediator;// 消息类型枚举
enum class MessageType {TEXT, // 普通文本消息SYSTEM, // 系统消息NOTIFICATION,// 通知消息COMMAND // 命令消息
};// 消息结构体
struct Message {std::string senderId;std::string receiverId; // 为空表示广播std::string content;MessageType type;std::string timestamp;std::unordered_map<std::string, std::string> metadata; // 附加信息
};// 消息过滤器接口
class MessageFilter {
public:virtual ~MessageFilter() = default;virtual bool filter(const Message& message, const User& receiver) = 0;virtual std::string getName() const = 0;
};// 抽象中介者:聊天室接口
class ChatRoomMediator {
public:virtual ~ChatRoomMediator() = default;// 注册用户virtual void registerUser(std::shared_ptr<User> user) = 0;// 移除用户virtual void unregisterUser(const std::string& userId) = 0;// 发送消息virtual bool sendMessage(const Message& message) = 0;// 获取用户virtual std::shared_ptr<User> getUser(const std::string& userId) const = 0;// 获取在线用户列表virtual std::vector<std::shared_ptr<User>> getOnlineUsers() const = 0;// 添加消息过滤器virtual void addFilter(std::unique_ptr<MessageFilter> filter) = 0;// 获取聊天室名称virtual std::string getRoomName() const = 0;
};// 抽象同事:用户接口
class User {
protected:ChatRoomMediator* mediator_; // 中介者引用std::string userId_; // 用户IDstd::string userName_; // 用户名std::unordered_set<std::string> blockedUsers_; // 被屏蔽的用户public:User(ChatRoomMediator* mediator, std::string userId, std::string userName): mediator_(mediator), userId_(std::move(userId)), userName_(std::move(userName)) {if (!mediator_) {throw std::invalid_argument("中介者对象不能为空");}}virtual ~User() = default;// 发送消息给指定用户bool sendTo(const std::string& receiverId, const std::string& content, MessageType type = MessageType::TEXT) {Message msg;msg.senderId = userId_;msg.receiverId = receiverId;msg.content = content;msg.type = type;return mediator_->sendMessage(msg);}// 广播消息给所有用户bool broadcast(const std::string& content, MessageType type = MessageType::TEXT) {Message msg;msg.senderId = userId_;msg.receiverId = ""; // 空表示广播msg.content = content;msg.type = type;return mediator_->sendMessage(msg);}// 接收消息(由子类实现)virtual void receive(const Message& message) = 0;// 屏蔽用户void blockUser(const std::string& userId) {blockedUsers_.insert(userId);std::cout << userName_ << " 已屏蔽用户 " << userId << std::endl;}// 解除屏蔽void unblockUser(const std::string& userId) {blockedUsers_.erase(userId);std::cout << userName_ << " 已解除屏蔽用户 " << userId << std::endl;}// 检查是否屏蔽了某个用户bool isUserBlocked(const std::string& userId) const {return blockedUsers_.find(userId) != blockedUsers_.end();}// 获取用户IDconst std::string& getUserId() const { return userId_; }// 获取用户名const std::string& getUserName() const { return userName_; }// 获取用户类型名称virtual std::string getUserType() const { return "普通用户"; }
};// 具体同事:普通用户
class RegularUser : public User {
public:RegularUser(ChatRoomMediator* mediator, std::string userId, std::string userName): User(mediator, std::move(userId), std::move(userName)) {}void receive(const Message& message) override {std::cout << "[" << message.timestamp << "] " << userName_ << " 收到来自 " << getSenderName(message.senderId) << " 的消息: " << message.content << std::endl;}private:// 获取发送者名称std::string getSenderName(const std::string& senderId) const {auto user = mediator_->getUser(senderId);return user ? user->getUserName() : "未知用户";}
};// 具体同事:VIP用户
class VIPUser : public User {
private:bool notificationsEnabled_ = true; // 是否启用消息通知bool isDoNotDisturb_ = false; // 免打扰模式public:VIPUser(ChatRoomMediator* mediator, std::string userId, std::string userName): User(mediator, std::move(userId), std::move(userName)) {}void receive(const Message& message) override {// 免打扰模式下只接收系统消息if (isDoNotDisturb_ && message.type != MessageType::SYSTEM) {std::cout << "[" << message.timestamp << "] [VIP] " << userName_ << " 处于免打扰模式,未接收来自 " << getSenderName(message.senderId) << " 的消息" << std::endl;return;}if (notificationsEnabled_) {std::cout << "[" << message.timestamp << "] [VIP] " << userName_ << " 收到来自 " << getSenderName(message.senderId) << " 的消息: " << message.content << std::endl;} else {std::cout << "[" << message.timestamp << "] [VIP] " << userName_ << " 的消息已静音: " << message.content << std::endl;}}// 启用/禁用消息通知void setNotificationsEnabled(bool enabled) {notificationsEnabled_ = enabled;std::cout << "[VIP] " << userName_ << " 的消息通知已" << (enabled ? "启用" : "禁用") << std::endl;}// 开启/关闭免打扰模式void setDoNotDisturb(bool enable) {isDoNotDisturb_ = enable;std::cout << "[VIP] " << userName_ << (enable ? " 已开启" : " 已关闭") << "免打扰模式" << std::endl;}std::string getUserType() const override { return "VIP用户"; }private:std::string getSenderName(const std::string& senderId) const {auto user = mediator_->getUser(senderId);return user ? user->getUserName() : "未知用户";}
};// 具体同事:管理员用户
class AdminUser : public User {
public:AdminUser(ChatRoomMediator* mediator, std::string userId, std::string userName): User(mediator, std::move(userId), std::move(userName)) {}void receive(const Message& message) override {std::cout << "[" << message.timestamp << "] [管理员] " << userName_ << " 收到来自 " << getSenderName(message.senderId) << " 的消息: " << message.content << std::endl;}// 踢出用户void kickUser(const std::string& userId) {if (userId == userId_) {std::cout << "[管理员] 不能踢出自己" << std::endl;return;}auto user = mediator_->getUser(userId);if (user) {std::cout << "[管理员] " << userName_ << " 将 " << user->getUserName() << " 踢出聊天室" << std::endl;mediator_->unregisterUser(userId);// 广播踢出消息broadcast(user->getUserName() + " 已被管理员移出聊天室", MessageType::SYSTEM);}}std::string getUserType() const override { return "管理员"; }private:std::string getSenderName(const std::string& senderId) const {auto user = mediator_->getUser(senderId);return user ? user->getUserName() : "未知用户";}
};// 具体过滤器:关键词过滤器
class KeywordFilter : public MessageFilter {
private:std::unordered_set<std::string> keywords_;std::string replacement_;public:KeywordFilter(std::unordered_set<std::string> keywords, std::string replacement = "***"): keywords_(std::move(keywords)), replacement_(std::move(replacement)) {}bool filter(Message& message, const User& /*receiver*/) override {if (message.type == MessageType::SYSTEM) {return true; // 系统消息不过滤}std::string modifiedContent = message.content;bool filtered = false;for (const auto& keyword : keywords_) {size_t pos = 0;while ((pos = modifiedContent.find(keyword, pos)) != std::string::npos) {modifiedContent.replace(pos, keyword.length(), replacement_);pos += replacement_.length();filtered = true;}}if (filtered) {message.content = modifiedContent;message.metadata["filtered"] = "true";}return true; // 始终允许通过(只是可能修改内容)}std::string getName() const override { return "关键词过滤器"; }
};// 具体过滤器:消息长度过滤器
class MessageLengthFilter : public MessageFilter {
private:size_t maxLength_;public:explicit MessageLengthFilter(size_t maxLength) : maxLength_(maxLength) {}bool filter(Message& message, const User& receiver) override {// 管理员不受长度限制if (receiver.getUserType() == "管理员") {return true;}if (message.content.length() > maxLength_) {message.content = message.content.substr(0, maxLength_) + "...";message.metadata["truncated"] = "true";}return true;}std::string getName() const override { return "消息长度过滤器"; }
};// 具体中介者:聊天室
class ChatRoom : public ChatRoomMediator {
private:std::unordered_map<std::string, std::shared_ptr<User>> users_; // 用户映射表std::string roomName_; // 聊天室名称std::vector<std::unique_ptr<MessageFilter>> filters_; // 消息过滤器std::unordered_map<std::string, std::vector<Message>> messageHistory_; // 消息历史// 获取当前时间戳std::string getCurrentTimestamp() const {auto now = std::chrono::system_clock::now();auto time = std::chrono::system_clock::to_time_t(now);auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch() % std::chrono::seconds(1));std::stringstream ss;ss << std::put_time(std::localtime(&time), "%H:%M:%S") << "." << std::setw(3) << std::setfill('0') << ms.count();return ss.str();}// 应用所有过滤器bool applyFilters(Message& message, const User& receiver) {for (const auto& filter : filters_) {if (!filter->filter(message, receiver)) {std::cout << "消息被 " << filter->getName() << " 拦截: " << message.content << std::endl;return false;}}return true;}public:explicit ChatRoom(std::string roomName) : roomName_(std::move(roomName)) {std::cout << "聊天室 '" << roomName_ << "' 创建成功" << std::endl;// 添加默认过滤器addFilter(std::make_unique<KeywordFilter>({"垃圾", "广告", "违规"}));addFilter(std::make_unique<MessageLengthFilter>(100));}// 注册用户void registerUser(std::shared_ptr<User> user) override {if (!user) {throw std::invalid_argument("用户对象不能为空");}const std::string& userId = user->getUserId();if (users_.find(userId) != users_.end()) {std::cout << user->getUserType() << " " << user->getUserName() << " 已在聊天室中" << std::endl;return;}users_[userId] = user;// 记录用户加入历史Message joinMsg;joinMsg.senderId = "";joinMsg.receiverId = "";joinMsg.content = user->getUserName() + " 加入了聊天室";joinMsg.type = MessageType::SYSTEM;joinMsg.timestamp = getCurrentTimestamp();messageHistory_["system"].push_back(joinMsg);// 广播加入消息sendMessage(joinMsg);std::cout << user->getUserType() << " " << user->getUserName() << " 已加入聊天室" << std::endl;}// 移除用户void unregisterUser(const std::string& userId) override {auto it = users_.find(userId);if (it != users_.end()) {std::shared_ptr<User> user = it->second;users_.erase(it);// 记录用户离开历史Message leaveMsg;leaveMsg.senderId = "";leaveMsg.receiverId = "";leaveMsg.content = user->getUserName() + " 离开了聊天室";leaveMsg.type = MessageType::SYSTEM;leaveMsg.timestamp = getCurrentTimestamp();messageHistory_["system"].push_back(leaveMsg);// 广播离开消息sendMessage(leaveMsg);std::cout << user->getUserType() << " " << user->getUserName() << " 已离开聊天室" << std::endl;}}// 发送消息bool sendMessage(const Message& message) override {// 填充消息元数据Message msg = message;msg.timestamp = getCurrentTimestamp();// 验证发送者if (!msg.senderId.empty() && users_.find(msg.senderId) == users_.end()) {std::cout << "错误: 发送者不存在或未加入聊天室" << std::endl;return false;}// 处理广播消息if (msg.receiverId.empty()) {// 广播给所有用户for (const auto& pair : users_) {// 不发送给发送者自己if (!msg.senderId.empty() && pair.first == msg.senderId) {continue;}// 检查接收者是否屏蔽了发送者if (!msg.senderId.empty() && pair.second->isUserBlocked(msg.senderId)) {continue;}// 应用过滤器Message filteredMsg = msg;if (applyFilters(filteredMsg, *pair.second)) {pair.second->receive(filteredMsg);}}// 记录广播消息if (!msg.senderId.empty()) {messageHistory_[msg.senderId].push_back(msg);}return true;}// 处理点对点消息auto receiverIt = users_.find(msg.receiverId);if (receiverIt == users_.end()) {std::cout << "错误: 接收者不存在或未加入聊天室" << std::endl;return false;}// 检查接收者是否屏蔽了发送者if (!msg.senderId.empty() && receiverIt->second->isUserBlocked(msg.senderId)) {std::cout << "消息被屏蔽: " << msg.content << std::endl;return false;}// 应用过滤器Message filteredMsg = msg;if (!applyFilters(filteredMsg, *receiverIt->second)) {return false;}// 发送消息receiverIt->second->receive(filteredMsg);// 记录点对点消息if (!msg.senderId.empty()) {messageHistory_[msg.senderId].push_back(msg);}return true;}// 获取用户std::shared_ptr<User> getUser(const std::string& userId) const override {auto it = users_.find(userId);return (it != users_.end()) ? it->second : nullptr;}// 获取在线用户列表std::vector<std::shared_ptr<User>> getOnlineUsers() const override {std::vector<std::shared_ptr<User>> users;for (const auto& pair : users_) {users.push_back(pair.second);}return users;}// 添加消息过滤器void addFilter(std::unique_ptr<MessageFilter> filter) override {if (filter) {filters_.push_back(std::move(filter));std::cout << "已添加过滤器: " << filters_.back()->getName() << std::endl;}}// 获取聊天室名称std::string getRoomName() const override {return roomName_;}// 显示房间信息void displayRoomInfo() const {std::cout << "\n=== 聊天室信息: " << roomName_ << " ===" << std::endl;std::cout << "在线用户数: " << users_.size() << std::endl;std::cout << "在线用户: ";for (const auto& pair : users_) {std::cout << pair.second->getUserName() << "(" << pair.second->getUserType() << ") ";}std::cout << "\n过滤器数量: " << filters_.size() << std::endl;std::cout << "===========================\n" << std::endl;}
};// 客户端代码
int main() {try {// 创建聊天室(中介者)ChatRoom chatRoom("设计模式讨论群");// 创建用户(同事)auto alice = std::make_shared<RegularUser>(&chatRoom, "U001", "Alice");auto bob = std::make_shared<VIPUser>(&chatRoom, "U002", "Bob");auto charlie = std::make_shared<AdminUser>(&chatRoom, "U003", "Charlie");// 用户加入聊天室chatRoom.registerUser(alice);chatRoom.registerUser(bob);chatRoom.registerUser(charlie);// 显示聊天室信息chatRoom.displayRoomInfo();// 发送消息std::cout << "\n--- 开始聊天 ---" << std::endl;alice->sendTo("U002", "你好 Bob,中介者模式怎么理解?");bob->sendTo("U001", "中介者模式主要是用来解耦多个对象之间的交互");charlie->broadcast("大家好!我是本聊天室的管理员");// 测试过滤功能alice->sendTo("U003", "这个垃圾模式太难理解了"); // 包含关键词"垃圾"alice->broadcast(std::string(150, 'a') + " 这个超长消息会被截断"); // 超长消息// Bob 设置免打扰auto vipBob = std::dynamic_pointer_cast<VIPUser>(bob);if (vipBob) {vipBob->setDoNotDisturb(true);alice->sendTo("U002", "Bob,你能再详细解释一下吗?");}// Alice 屏蔽 Bobalice->blockUser("U002");bob->sendTo("U001", "Alice,你能收到这条消息吗?"); // 会被屏蔽// 管理员踢出用户auto adminCharlie = std::dynamic_pointer_cast<AdminUser>(charlie);if (adminCharlie) {adminCharlie->kickUser("U002"); // 踢出Bob}// 继续聊天std::cout << "\n--- 继续聊天 ---" << std::endl;alice->sendTo("U003", "Charlie,中介者模式有什么应用场景?");charlie->sendTo("U001", "很多地方都能用,比如聊天系统、GUI组件交互等");} catch (const std::exception& e) {std::cerr << "发生错误: " << e.what() << std::endl;return 1;}return 0;
}
优化后的优势
- 更高的灵活性
- 消息过滤规则可动态配置,适应不同场景需求
- 用户类型可灵活扩展,无需修改现有交互逻辑
- 更强的功能完整性
- 支持真实聊天系统所需的核心功能(屏蔽、踢人、免打扰等)
- 消息处理更智能,能应对各种复杂交互场景
- 更好的可维护性
- 职责划分清晰,每个类专注于单一功能
- 采用接口驱动设计,代码结构清晰,易于理解和修改
- 更强的可扩展性
- 新增用户类型只需继承
User
类 - 新增过滤规则只需实现
MessageFilter
接口 - 可轻松添加新功能(如消息撤回、已读状态等)
- 新增用户类型只需继承