中介者模式(Mediator Pattern)是一种行为型设计模式,其核心思想是通过引入一个"中介者"对象,封装多个对象(称为"同事对象")之间的复杂交互关系,使同事对象无需直接相互引用,而是通过中介者间接通信。这种模式本质上是**"迪米特法则"(最少知识原则)** 的极致体现,旨在解耦对象间的网状依赖,将多对多关系转化为中介者与同事对象之间的一对多关系。
一、介绍
核心角色
- 抽象中介者(Mediator): 定义中介者与同事对象交互的接口,通常包含"注册同事"和"转发请求"的抽象方法。
- 具体中介者(ConcreteMediator): |实现抽象中介者接口,维护所有同事对象的引用,协调同事对象的交互逻辑。
- 抽象同事(Colleague): 定义同事对象的公共接口,持有抽象中介者的引用,确保同事能通过中介者通信。
- 具体同事(ConcreteColleague): |实现抽象同事接口,自身业务逻辑与中介者交互(而非直接与其他同事交互)。
优点
- 降低耦合度
- 将多对多的对象关系转化为一对多的关系,减少对象间的直接依赖
- 每个对象只需关注自身业务逻辑,无需了解其他对象的具体实现
- 集中控制交互
- 所有对象间的交互逻辑集中在中介者中,便于理解和维护
- 变更交互规则时,只需修改中介者,无需修改各个对象
- 简化对象协议
- 对象间无需制定复杂的交互协议,只需与中介者通信
- 新对象加入系统时,只需与中介者交互即可,无需修改现有对象
- 提高可扩展性
- 新增对象时,只需在中介者中添加相应的处理逻辑
- 可以通过扩展中介者来实现新的交互规则
- 符合迪米特法则
- 每个对象只需要了解中介者,不需要了解其他对象
- 减少了对象之间的通信开销和复杂度
适用场景
- 多个对象之间存在复杂交互关系
- 当系统中对象数量较多,且对象之间存在多对多的交互关系,形成复杂的网络结构时
- 例如:聊天室中用户之间的消息传递、游戏中多个角色之间的互动
- 需要简化对象间通信
- 当对象间的直接引用导致系统难以理解和维护时
- 例如:GUI界面中多个控件(按钮、文本框、列表等)之间的联动
- 需要集中管理对象交互逻辑
- 当对象间的交互规则复杂,且可能频繁变化时
- 例如:电商平台中订单、库存、支付、物流等模块之间的协作
- 需要减少对象间的耦合度
- 当希望提高系统的可复用性和可扩展性时
- 例如:微服务架构中的服务协调器、分布式系统中的中间件
二、实现
以聊天室系统为例,展示如何使用中介者模式管理用户之间的消息交互
cpp
#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_; // 用户ID
std::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;
// 获取用户ID
const 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的免打扰模式、管理员的踢人功能
- 实现用户屏蔽功能,增强交互控制
- 增强中介者功能
- 添加消息历史记录,便于追踪和回溯
- 完善用户管理(注册/移除/查询)
- 支持聊天室信息展示,提高系统透明度
- 提高代码可扩展性
- 采用接口和抽象类设计,便于新增用户类型和过滤器
- 使用组合而非继承扩展功能,符合开闭原则
- 松耦合设计使新增功能(如文件传输、表情系统)更容易实现
- 增强错误处理与健壮性
- 添加参数验证和异常处理
- 处理边界情况(如发送给不存在的用户、自己踢自己等)
- 完善状态检查,避免空指针等常见错误
cpp
#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_; // 用户ID
std::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();
}
// 获取用户ID
const 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 屏蔽 Bob
alice->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
接口 - 可轻松添加新功能(如消息撤回、已读状态等)
- 新增用户类型只需继承