C++设计模式之行为型模式:中介者模式(Mediator)

中介者模式(Mediator)是行为型设计模式的一种,它通过引入一个中介者对象来简化多个对象之间的交互,使对象之间不再直接通信,而是通过中介者间接交互,从而降低对象间的耦合度。这种模式类似于现实生活中的"中介"或"协调者",如机场塔台协调飞机起降、项目经理协调团队成员工作。

一、核心思想与角色

中介者模式的核心是"集中控制交互,减少直接依赖",通过中介者封装对象间的复杂交互逻辑。其核心角色如下:

角色名称 核心职责
抽象中介者(Mediator) 定义中介者与同事对象交互的接口,声明协调同事对象的方法。
具体中介者(ConcreteMediator) 实现抽象中介者接口,持有所有同事对象的引用,协调同事对象的交互(如转发消息)。
抽象同事(Colleague) 定义同事对象的接口,包含一个指向中介者的引用,提供与中介者通信的方法。
具体同事(ConcreteColleague) 实现抽象同事接口,当需要与其他同事交互时,通过中介者转发请求,不直接与其他同事通信。

核心思想:将多个对象之间的多对多交互转换为中介者与各个对象之间的一对多交互,使对象间的依赖关系简化,便于维护和扩展。

二、实现示例(聊天室系统)

假设我们需要设计一个聊天室系统,多个用户(同事)可以在聊天室中发送消息,所有用户能收到其他人的消息。使用中介者模式可避免用户之间直接通信,由聊天室(中介者)统一转发消息:

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

// 1. 抽象同事:用户
class User; // 前向声明

// 1. 抽象中介者:聊天室
class ChatRoom {
public:
    virtual void registerUser(User* user) = 0; // 注册用户
    virtual void sendMessage(const std::string& message, User* sender) = 0; // 转发消息
    virtual ~ChatRoom() = default;
};

// 2. 抽象同事:用户
class User {
protected:
    ChatRoom* mediator; // 指向中介者(聊天室)
    std::string name;   // 用户名

public:
    User(ChatRoom* m, const std::string& n) : mediator(m), name(n) {
        // 注册到聊天室
        mediator->registerUser(this);
    }

    virtual ~User() = default;

    // 获取用户名
    std::string getName() const {
        return name;
    }

    // 发送消息(通过中介者)
    virtual void send(const std::string& message) {
        mediator->sendMessage(message, this);
    }

    // 接收消息
    virtual void receive(const std::string& message, const std::string& senderName) {
        std::cout << "[" << senderName << " 发送给 " << name << "]: " << message << std::endl;
    }
};

// 3. 具体中介者:具体聊天室
class ConcreteChatRoom : public ChatRoom {
private:
    std::vector<User*> users; // 存储所有用户

public:
    // 注册用户到聊天室
    void registerUser(User* user) override {
        users.push_back(user);
    }

    // 转发消息:向所有其他用户发送消息
    void sendMessage(const std::string& message, User* sender) override {
        std::string senderName = sender->getName();
        // 遍历所有用户,排除发送者自身
        for (User* user : users) {
            if (user != sender) {
                user->receive(message, senderName);
            }
        }
    }
};

// 3. 具体同事:普通用户
class RegularUser : public User {
public:
    RegularUser(ChatRoom* m, const std::string& n) : User(m, n) {}
};

// 3. 具体同事:VIP用户(扩展功能)
class VIPUser : public User {
public:
    VIPUser(ChatRoom* m, const std::string& n) : User(m, n) {}

    // VIP用户发送的消息带特殊标识
    void send(const std::string& message) override {
        mediator->sendMessage("[VIP消息] " + message, this);
    }

    // VIP用户接收消息的提示不同
    void receive(const std::string& message, const std::string& senderName) override {
        std::cout << "[VIP提醒] " << senderName << " 给您发消息: " << message << std::endl;
    }
};

// 客户端代码:使用聊天室
int main() {
    // 创建中介者(聊天室)
    ChatRoom* chatRoom = new ConcreteChatRoom();

    // 创建同事(用户),自动注册到聊天室
    User* alice = new RegularUser(chatRoom, "Alice");
    User* bob = new VIPUser(chatRoom, "Bob");
    User* charlie = new RegularUser(chatRoom, "Charlie");

    // 发送消息(通过中介者转发)
    std::cout << "=== Alice发送消息 ===" << std::endl;
    alice->send("大家好!");

    std::cout << "\n=== Bob发送消息 ===" << std::endl;
    bob->send("我是VIP用户,有问题可以找我~");

    std::cout << "\n=== Charlie发送消息 ===" << std::endl;
    charlie->send("请问有人知道今天的会议时间吗?");

    // 释放资源
    delete charlie;
    delete bob;
    delete alice;
    delete chatRoom;

    return 0;
}

三、代码解析

  1. 抽象中介者(ChatRoom)

    定义了registerUser()(注册用户)和sendMessage()(转发消息)接口,是聊天室与用户交互的规范。

  2. 具体中介者(ConcreteChatRoom)

    • 持有所有用户的引用(users列表),负责管理用户注册。
    • 实现sendMessage()方法,将消息转发给除发送者外的所有用户,集中处理用户间的通信逻辑。
  3. 抽象同事(User)

    • 包含指向中介者的引用(mediator)和用户名(name)。
    • 提供send()方法(通过中介者发送消息)和receive()方法(接收消息),定义了用户的基本行为。
  4. 具体同事

    • RegularUser:普通用户,使用默认的send()receive()实现。
    • VIPUser:VIP用户,重写send()(消息带VIP标识)和receive()(接收提示不同),扩展了功能但仍通过中介者通信。
  5. 客户端使用

    客户端创建聊天室(中介者)和用户(同事),用户通过send()方法发送消息,无需知道其他用户的存在,所有交互由聊天室中介者协调。

四、核心优势与适用场景

优势
  1. 降低耦合度:将对象间的多对多依赖转换为一对多依赖,减少对象间的直接关联,便于维护。
  2. 集中控制交互:所有交互逻辑集中在中介者中,避免交互逻辑分散在多个对象中导致的混乱。
  3. 简化对象设计:同事对象只需关注自身功能,无需处理与其他对象的通信细节,设计更简洁。
  4. 易于扩展:新增同事对象或修改交互规则时,只需修改中介者,无需修改多个同事对象(符合开闭原则)。
适用场景
  1. 对象间存在复杂交互:当系统中多个对象之间存在频繁且复杂的通信(如聊天室、多人游戏、GUI组件交互)。
  2. 需要减少对象耦合:当对象间直接引用导致耦合度过高,难以修改或扩展时。
  3. 希望集中管理交互:当需要统一控制对象间的交互规则(如权限控制、消息过滤)时。

五、局限性与与其他模式的区别

局限性
  1. 中介者可能变复杂:随着交互逻辑增多,中介者类可能变得庞大复杂,成为"上帝类",难以维护。
  2. 过度集中风险:所有交互依赖中介者,一旦中介者出现问题,整个系统可能受影响。
与其他模式的区别
模式 核心差异点
中介者模式 集中管理对象间的交互,使对象通过中介者间接通信,强调"交互集中控制"。
观察者模式 一个对象通知多个观察者,观察者被动接收通知,强调"单向依赖与事件通知"。
外观模式 为复杂子系统提供简化接口,不涉及对象间的交互协调,强调"接口简化"。
代理模式 控制对单个对象的访问,不处理多个对象间的交互,强调"访问控制"。

六、实践建议

  1. 拆分复杂中介者:当中介者逻辑过于复杂时,可将其拆分为多个 smaller 中介者(如按功能模块拆分),避免"上帝类"。
  2. 结合观察者模式:中介者与同事间的通信可通过观察者模式实现(同事注册为中介者的观察者),使交互更灵活。
  3. 避免过度使用:简单的对象交互无需引入中介者,否则会增加系统复杂度。
  4. 明确中介者职责:中介者应只负责协调交互,不包含业务逻辑,业务逻辑仍由同事对象实现。

中介者模式的核心价值在于"简化对象间的交互,降低系统耦合"。它通过引入中介者角色,将分散的交互逻辑集中管理,使系统结构更清晰,易于维护和扩展。在多对象交互频繁的场景中,中介者模式是化解对象间复杂依赖的有效方案。

相关推荐
敢敢J的憨憨L3 小时前
GPTL(General Purpose Timing Library)使用教程
java·服务器·前端·c++·轻量级计时工具库
小欣加油3 小时前
leetcode 62 不同路径
c++·算法·leetcode·职场和发展
让我们一起加油好吗4 小时前
【C++】封装红黑树模拟实现 set 和 map
linux·c++·set·map·红黑树
hsjkdhs4 小时前
C++之类的继承与派生
开发语言·c++
冷徹 .4 小时前
2024ICPC区域赛香港站
数据结构·c++·算法
沐怡旸4 小时前
【底层机制】std:: function 解决的痛点?是什么?如何实现?如何正确用?
c++·面试
浅川.255 小时前
xtuoj string
开发语言·c++·算法
Meteors.5 小时前
23种设计模式——责任链模式(Chain of Responsibility Pattern)
设计模式·责任链模式
o0向阳而生0o6 小时前
107、23种设计模式之观察者模式(16/23)
观察者模式·设计模式