中介者模式

1. 模式定义

中介者模式是一种行为设计模式,它通过引入一个中介对象来封装一系列对象之间的交互,从而降低这些对象之间的耦合度。中介者使对象之间不需要显式地相互引用,从而使其可以独立地改变它们之间的交互。

2. 核心思想

用一个中介对象来封装多个对象间的交互关系,使得各对象不需要显式地相互引用,从而降低耦合度,并可以独立地改变它们之间的交互。

解耦多个同事对象之间的交互关系。每个对象都持有中介者对象的引用,只跟中介者对象打交道。我们通过中介者对象统一管理这些交互关系。

3. 主要角色

  • Mediator(抽象中介者):定义同事对象到中介者对象的接口

  • ConcreteMediator(具体中介者):实现抽象中介者的接口,协调各个同事对象的交互

  • Colleague(同事类):每个同事对象都知道它的中介者对象,同事对象之间不直接通信,而是通过中介者进行通信

  • ConcreteColleague(具体同事类):实现同事类的接口

4. 应用场景

  1. 系统中对象之间存在复杂的引用关系,导致依赖关系结构混乱且难以复用

  2. 多个对象之间的交互操作紧密耦合,导致难以独立修改这些行为

  3. 需要定义一个分布在多个类中的行为,但又不想生成太多子类

5. 模式优缺点

优点:

  1. 降低耦合度:将多个对象间的交互封装在中介者中,对象间不直接引用

  2. 集中控制:将交互逻辑集中在中介者中,便于维护和修改

  3. 简化对象协议:用一对多的交互代替多对多的交互

  4. 提高可复用性:同事类之间不直接通信,可以独立变化和复用

缺点:

  1. 中介者复杂化:中介者可能变得过于复杂,承担过多责任

  2. 性能影响:对象间通信必须通过中介者,可能影响性能

  3. 单点故障:中介者成为系统瓶颈,中介者故障会影响整个系统

代码

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include <ctime>

// 前向声明
class User;

// 抽象中介者:聊天室
class ChatRoomMediator {
public:
    virtual ~ChatRoomMediator() = default;
    virtual void sendMessage(const std::string& message, User* user) = 0;
    virtual void addUser(User* user) = 0;
};

// 抽象同事类:用户
class User {
protected:
    ChatRoomMediator* mediator;
    std::string name;
    
public:
    User(const std::string& name, ChatRoomMediator* mediator) 
        : name(name), mediator(mediator) {
        if (mediator) {
            mediator->addUser(this);
        }
    }
    
    virtual ~User() = default;
    
    virtual void send(const std::string& message) = 0;
    virtual void receive(const std::string& message) = 0;
    
    std::string getName() const {
        return name;
    }
    
    void setMediator(ChatRoomMediator* newMediator) {
        mediator = newMediator;
    }
};
cpp 复制代码
// 具体中介者:聊天室
class ChatRoom : public ChatRoomMediator {
private:
    std::string name;
    std::vector<User*> users;
    
    std::string getCurrentTime() {
        time_t now = time(0);
        char* dt = ctime(&now);
        std::string timeStr(dt);
        // 移除换行符
        if (!timeStr.empty() && timeStr[timeStr.length()-1] == '\n') {
            timeStr.erase(timeStr.length()-1);
        }
        return timeStr;
    }
    
public:
    explicit ChatRoom(const std::string& name) : name(name) {
        std::cout << "聊天室 '" << name << "' 已创建\n";
    }
    
    void addUser(User* user) override {
        users.push_back(user);
        std::cout << "用户 '" << user->getName() << "' 加入了聊天室 '" << name << "'\n";
    }
    
    void sendMessage(const std::string& message, User* sender) override {
        std::string formattedMessage = "[" + getCurrentTime() + "] " + 
                                      sender->getName() + ": " + message;
        
        std::cout << "聊天室 '" << name << "' 转发消息: " << formattedMessage << "\n";
        
        // 广播消息给所有用户(除了发送者)
        for (User* user : users) {
            if (user != sender) {
                user->receive(formattedMessage);
            }
        }
    }
    
    // 私聊功能
    void sendPrivateMessage(const std::string& message, User* sender, User* receiver) {
        std::string formattedMessage = "[" + getCurrentTime() + "] [私聊] " + 
                                      sender->getName() + " 对你说: " + message;
        
        std::cout << "聊天室 '" << name << "' 转发私聊消息\n";
        receiver->receive(formattedMessage);
    }
    
    // 获取在线用户列表
    void listUsers() const {
        std::cout << "聊天室 '" << name << "' 在线用户 (" << users.size() << "人):\n";
        for (const User* user : users) {
            std::cout << "  - " << user->getName() << "\n";
        }
    }
    
    std::string getName() const {
        return name;
    }
};
cpp 复制代码
// 具体同事类:普通用户
class RegularUser : public User {
public:
    RegularUser(const std::string& name, ChatRoomMediator* mediator)
        : User(name, mediator) {}
    
    void send(const std::string& message) override {
        std::cout << name << " 发送消息: " << message << "\n";
        if (mediator) {
            mediator->sendMessage(message, this);
        }
    }
    
    void receive(const std::string& message) override {
        std::cout << name << " 收到消息: " << message << "\n";
    }
};

// 具体同事类:管理员用户
class AdminUser : public User {
public:
    AdminUser(const std::string& name, ChatRoomMediator* mediator)
        : User(name, mediator) {}
    
    void send(const std::string& message) override {
        std::cout << "[管理员] " << name << " 发送消息: " << message << "\n";
        if (mediator) {
            mediator->sendMessage(message, this);
        }
    }
    
    void receive(const std::string& message) override {
        std::cout << "[管理员] " << name << " 收到消息: " << message << "\n";
    }
    
    void sendAnnouncement(const std::string& announcement) {
        std::string formattedMsg = "【系统公告】" + announcement;
        send(formattedMsg);
    }
};

// 具体同事类:机器人用户
class BotUser : public User {
private:
    std::vector<std::pair<std::string, std::string>> responses = {
        {"你好", "你好!我是聊天机器人。"},
        {"天气", "今天天气晴朗,气温25度。"},
        {"时间", "当前时间是: "},
        {"帮助", "我可以回答: 你好, 天气, 时间, 帮助"}
    };
    
public:
    BotUser(const std::string& name, ChatRoomMediator* mediator)
        : User(name, mediator) {}
    
    void send(const std::string& message) override {
        // 机器人通常不主动发送消息
        std::cout << "[机器人] " << name << " 处理消息: " << message << "\n";
    }
    
    void receive(const std::string& message) override {
        std::cout << "[机器人] " << name << " 收到消息: " << message << "\n";
        
        // 检查是否需要响应
        for (const auto& pair : responses) {
            if (message.find(pair.first) != std::string::npos) {
                std::string response = pair.second;
                if (pair.first == "时间") {
                    response += ChatRoom("").getCurrentTime(); // 获取时间
                }
                send(response);
                break;
            }
        }
    }
};
cpp 复制代码
int main() {
    std::cout << "===== 聊天室系统演示 =====\n\n";
    
    // 创建聊天室(中介者)
    ChatRoom mainChatRoom("主聊天室");
    ChatRoom gameChatRoom("游戏聊天室");
    
    // 创建用户(同事类)
    RegularUser alice("Alice", &mainChatRoom);
    RegularUser bob("Bob", &mainChatRoom);
    AdminUser admin("系统管理员", &mainChatRoom);
    BotUser chatbot("小助手", &mainChatRoom);
    
    std::cout << "\n";
    
    // 显示在线用户
    mainChatRoom.listUsers();
    std::cout << "\n";
    
    // 用户间发送消息(通过中介者)
    std::cout << "=== 开始聊天 ===\n";
    alice.send("大家好,我是Alice!");
    std::cout << "\n";
    
    bob.send("你好Alice,我是Bob!");
    std::cout << "\n";
    
    admin.sendAnnouncement("欢迎新用户加入聊天室!");
    std::cout << "\n";
    
    // 测试机器人响应
    alice.send("小助手,你好");
    std::cout << "\n";
    
    bob.send("小助手,今天天气怎么样?");
    std::cout << "\n";
    
    alice.send("小助手,现在几点了?");
    std::cout << "\n";
    
    // 用户切换到另一个聊天室
    std::cout << "\n=== 切换聊天室 ===\n";
    alice.setMediator(&gameChatRoom);
    gameChatRoom.addUser(&alice);
    std::cout << "\n";
    
    bob.setMediator(&gameChatRoom);
    gameChatRoom.addUser(&bob);
    std::cout << "\n";
    
    // 在新聊天室中聊天
    gameChatRoom.listUsers();
    std::cout << "\n";
    
    alice.send("有人要一起玩游戏吗?");
    std::cout << "\n";
    
    bob.send("好啊,Alice!玩什么游戏?");
    std::cout << "\n";
    
    // 私聊功能演示
    std::cout << "\n=== 私聊功能 ===\n";
    gameChatRoom.sendPrivateMessage("我们玩英雄联盟吧?", &alice, &bob);
    std::cout << "\n";
    
    return 0;
}
相关推荐
Engineer邓祥浩1 天前
设计模式学习(20) 23-18 中介者模式
学习·设计模式·中介者模式
小码过河.10 天前
设计模式——中介者模式
中介者模式
Geoking.11 天前
【设计模式】中介者模式(Mediator)详解
java·设计模式·中介者模式
胖虎115 天前
iOS中的设计模式(十)- 中介者模式(从播放器场景理解中介者模式)
设计模式·中介者模式·解耦·ios中的设计模式
刀法孜然15 天前
23种设计模式 3 行为型模式 之3.6 mediator 中介者模式
设计模式·中介者模式
a35354138220 天前
设计模式-中介者模式
c++·设计模式·中介者模式
JavaBoy_XJ1 个月前
行为型-中介者模式
中介者模式
__万波__1 个月前
二十三种设计模式(十八)--中介者模式
java·设计模式·中介者模式
syt_10131 个月前
设计模式之-中介者模式
设计模式·中介者模式