中介者模式及优化

中介者模式(Mediator Pattern)是一种行为型设计模式,其核心思想是通过引入一个"中介者"对象,封装多个对象(称为"同事对象")之间的复杂交互关系,使同事对象无需直接相互引用,而是通过中介者间接通信。这种模式本质上是**"迪米特法则"(最少知识原则)** 的极致体现,旨在解耦对象间的网状依赖,将多对多关系转化为中介者与同事对象之间的一对多关系。

一、介绍

核心角色
  1. 抽象中介者(Mediator): 定义中介者与同事对象交互的接口,通常包含"注册同事"和"转发请求"的抽象方法。
  2. 具体中介者(ConcreteMediator): |实现抽象中介者接口,维护所有同事对象的引用,协调同事对象的交互逻辑。
  3. 抽象同事(Colleague): 定义同事对象的公共接口,持有抽象中介者的引用,确保同事能通过中介者通信。
  4. 具体同事(ConcreteColleague): |实现抽象同事接口,自身业务逻辑与中介者交互(而非直接与其他同事交互)。
优点
  1. 降低耦合度
    • 将多对多的对象关系转化为一对多的关系,减少对象间的直接依赖
    • 每个对象只需关注自身业务逻辑,无需了解其他对象的具体实现
  2. 集中控制交互
    • 所有对象间的交互逻辑集中在中介者中,便于理解和维护
    • 变更交互规则时,只需修改中介者,无需修改各个对象
  3. 简化对象协议
    • 对象间无需制定复杂的交互协议,只需与中介者通信
    • 新对象加入系统时,只需与中介者交互即可,无需修改现有对象
  4. 提高可扩展性
    • 新增对象时,只需在中介者中添加相应的处理逻辑
    • 可以通过扩展中介者来实现新的交互规则
  5. 符合迪米特法则
    • 每个对象只需要了解中介者,不需要了解其他对象
    • 减少了对象之间的通信开销和复杂度
适用场景
  1. 多个对象之间存在复杂交互关系
    • 当系统中对象数量较多,且对象之间存在多对多的交互关系,形成复杂的网络结构时
    • 例如:聊天室中用户之间的消息传递、游戏中多个角色之间的互动
  2. 需要简化对象间通信
    • 当对象间的直接引用导致系统难以理解和维护时
    • 例如:GUI界面中多个控件(按钮、文本框、列表等)之间的联动
  3. 需要集中管理对象交互逻辑
    • 当对象间的交互规则复杂,且可能频繁变化时
    • 例如:电商平台中订单、库存、支付、物流等模块之间的协作
  4. 需要减少对象间的耦合度
    • 当希望提高系统的可复用性和可扩展性时
    • 例如:微服务架构中的服务协调器、分布式系统中的中间件

二、实现

以聊天室系统为例,展示如何使用中介者模式管理用户之间的消息交互

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 的消息: 用过,在设计聊天系统时特别有用
应用场景
  1. 通信系统
    • 聊天室、即时通讯软件中的消息转发机制
    • 电话交换机、路由器等网络设备
  2. GUI框架
    • 窗口管理器协调多个控件之间的交互
    • 如Qt中的QWidget和信号槽机制
  3. 游戏开发
    • 游戏世界管理器协调玩家、NPC、物品之间的交互
    • 碰撞检测系统处理游戏对象之间的碰撞关系
  4. 企业应用
    • 工作流引擎协调各个业务节点的执行顺序
    • 订单处理系统协调库存、支付、物流等模块
  5. 分布式系统
    • 服务注册中心协调微服务之间的通信
    • 消息队列中间件(如RabbitMQ、Kafka)作为中介者转发消息

三、优化

优化点
  1. 引入消息类型与结构
    • 定义Message结构体封装消息内容、发送者、接收者、时间戳等元数据
    • 增加MessageType枚举区分不同类型消息(文本、系统、通知等)
    • 支持消息附加信息(metadata),增强扩展性
  2. 添加消息过滤机制
    • 引入MessageFilter接口,实现关键词过滤、长度限制等功能
    • 支持动态添加过滤器,无需修改核心逻辑
    • 不同用户类型可应用不同过滤规则(如管理员不受长度限制)
  3. 丰富用户类型与权限
    • 扩展用户类型:普通用户、VIP用户、管理员
    • 为不同用户添加专属功能:VIP的免打扰模式、管理员的踢人功能
    • 实现用户屏蔽功能,增强交互控制
  4. 增强中介者功能
    • 添加消息历史记录,便于追踪和回溯
    • 完善用户管理(注册/移除/查询)
    • 支持聊天室信息展示,提高系统透明度
  5. 提高代码可扩展性
    • 采用接口和抽象类设计,便于新增用户类型和过滤器
    • 使用组合而非继承扩展功能,符合开闭原则
    • 松耦合设计使新增功能(如文件传输、表情系统)更容易实现
  6. 增强错误处理与健壮性
    • 添加参数验证和异常处理
    • 处理边界情况(如发送给不存在的用户、自己踢自己等)
    • 完善状态检查,避免空指针等常见错误
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;
}   
优化后的优势
  1. 更高的灵活性
    • 消息过滤规则可动态配置,适应不同场景需求
    • 用户类型可灵活扩展,无需修改现有交互逻辑
  2. 更强的功能完整性
    • 支持真实聊天系统所需的核心功能(屏蔽、踢人、免打扰等)
    • 消息处理更智能,能应对各种复杂交互场景
  3. 更好的可维护性
    • 职责划分清晰,每个类专注于单一功能
    • 采用接口驱动设计,代码结构清晰,易于理解和修改
  4. 更强的可扩展性
    • 新增用户类型只需继承User
    • 新增过滤规则只需实现MessageFilter接口
    • 可轻松添加新功能(如消息撤回、已读状态等)
相关推荐
yw00yw20 分钟前
常见的设计模式
开发语言·javascript·设计模式
我们从未走散22 分钟前
设计模式学习笔记-----抽象责任链模式
java·笔记·学习·设计模式·责任链模式
重启的码农1 小时前
Windows虚拟显示器MttVDD源码分析 (6) 高级色彩与HDR管理
c++·windows·操作系统
jingfeng5141 小时前
C++多态
开发语言·c++
kyle~2 小时前
C/C++---浮点数与整形的转换,为什么使用sqrt函数时,要给参数加上一个极小的小数(如1e-6)
c语言·开发语言·c++
jokr_2 小时前
C++ STL 专家容器:关联式、哈希与适配器
java·c++·哈希算法
倔强的石头3 小时前
java程序员如何搭建C++windows开发环境搭建(二)
c++·后端
别再问我单例了3 小时前
01-设计模式系列之---七大原则助你高效开发(完整版)
设计模式
哆啦code梦3 小时前
设计模式之命令模式
设计模式·命令模式
The Chosen One9853 小时前
红黑树下探玄机:C++ map&multimap 的幕后之旅
开发语言·c++