目录

C设计模式第十七篇中介者模式Mediator

​【C++设计模式】第十七篇:中介者模式(Mediator)

注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。

集中式交互调度中心


1. 模式定义与用途

核心思想

  • 中介者模式 :通过 中介者对象 集中管理多个对象间的交互,使其 无需直接引用彼此 ,从而降低耦合度。

  • 关键用途

    ​1. 解耦对象间依赖 :避免对象间形成复杂的网状引用关系。

    ​2. 集中控制交互逻辑 :统一管理消息路由、权限校验等公共逻辑。

经典场景

  • 聊天室(用户发送消息由聊天室中转)。
  • 飞机与塔台通信(所有通信通过塔台调度)。
  • GUI组件交互(按钮点击触发面板显示,通过中介者协调)。

2. 模式结构解析

UML类图

+---------------------+          +---------------------+  
|      Mediator       |          |      Colleague      |  
+---------------------+          +---------------------+  
| + notify(sender, msg)|<|---------| - mediator: Mediator |  
+---------------------+          +---------------------+  
          ^                                ^  
          |                                |  
  +-------+-------+              +---------+---------+  
  |               |              |                   |  
+---------------------+    +--------------------+ +--------------------+  
| ConcreteMediator    |    | ConcreteColleagueA | | ConcreteColleagueB |  
+---------------------+    +--------------------+ +--------------------+  
| + notify()          |    | + send()           | | + send()           |  
+---------------------+    +--------------------+ +--------------------+  

角色说明

  1. Mediator :中介者接口,定义对象间通信的方法(如 notify )。
  2. ​ConcreteMediator :具体中介者,实现协调逻辑(如消息转发)。
  3. Colleague :同事类接口,持有中介者引用,并通过中介者通信。
  4. ConcreteColleague :具体同事类,触发事件并通知中介者。

3. 现代C++实现示例

场景:聊天室消息中转

​步骤1:定义中介者与同事接口
#include <iostream>  
#include <string>  
#include <vector>  
#include <memory>  

class User;  

// 中介者接口  
class ChatMediator {  
public:  
    virtual ~ChatMediator() = default;  
    virtual void broadcast(const std::string& msg, const User* sender) = 0;  
};  

// 同事类接口  
class User {  
public:  
    User(const std::string& name, ChatMediator* mediator)  
        : name_(name), mediator_(mediator) {}  
    virtual ~User() = default;  

    void send(const std::string& msg) {  
        std::cout << name_ << " 发送消息: " << msg << "\n";  
        mediator_->broadcast(msg, this);  
    }  

    virtual void receive(const std::string& msg) {  
        std::cout << name_ << " 收到消息: " << msg << "\n";  
    }  

protected:  
    std::string name_;  
    ChatMediator* mediator_;  
};  
步骤2:实现具体中介者
class ChatRoom : public ChatMediator {  
public:  
    void addUser(std::shared_ptr<User> user) {  
        users_.push_back(user);  
    }  

    void broadcast(const std::string& msg, const User* sender) override {  
        for (auto& user : users_) {  
            if (user.get() != sender) {  // 不将消息发送给自己  
                user->receive(msg);  
            }  
        }  
    }  

private:  
    std::vector<std::shared_ptr<User>> users_;  
};  
步骤3:实现具体同事类(用户)
class ChatUser : public User {  
public:  
    using User::User;  

    void receive(const std::string& msg) override {  
        std::cout << "[私信] ";  
        User::receive(msg);  
    }  
};  
步骤4:客户端代码
int main() {  
    auto chatRoom = std::make_shared<ChatRoom>();  

    auto alice = std::make_shared<ChatUser>("Alice", chatRoom.get());  
    auto bob = std::make_shared<ChatUser>("Bob", chatRoom.get());  
    chatRoom->addUser(alice);  
    chatRoom->addUser(bob);  

    alice->send("大家好!");  
    bob->send("欢迎Alice!");  
}  

/* 输出:  
Alice 发送消息: 大家好!  
[私信] Bob 收到消息: 大家好!  
Bob 发送消息: 欢迎Alice!  
[私信] Alice 收到消息: 欢迎Alice!  
*/  

4. 应用场景示例

​场景1:GUI组件交互(按钮与面板)

class Button;  
class Panel;  

class GUIMediator {  
public:  
    virtual void buttonClicked(Button* btn) = 0;  
};  

class Button {  
public:  
    Button(GUIMediator* mediator) : mediator_(mediator) {}  
    void click() { mediator_->buttonClicked(this); }  

private:  
    GUIMediator* mediator_;  
};  

class Panel : public GUIMediator {  
public:  
    void buttonClicked(Button* btn) override {  
        std::cout << "面板刷新显示\n";  
    }  
};  

场景2:航班调度系统

class Airplane;  

class ControlTower : public Mediator {  
public:  
    void requestLanding(Airplane* plane) {  
        std::cout << "塔台允许 " << plane->getId() << " 降落\n";  
    }  
};  

class Airplane {  
public:  
    Airplane(const std::string& id, ControlTower* tower)  
        : id_(id), tower_(tower) {}  
    void land() { tower_->requestLanding(this); }  
    const std::string& getId() const { return id_; }  

private:  
    std::string id_;  
    ControlTower* tower_;  
};  

5. 优缺点分析

​优点​缺点
减少对象间直接依赖,简化系统结构中介者类可能变得臃肿(需处理所有交互)
新增同事类无需修改现有代码中介者可能成为单点故障
集中管理交互逻辑(如权限、日志)过度使用会掩盖对象间自然关系

6. 调试与优化策略

调试技巧(VS2022)​

1. ​跟踪消息路由:
  • broadcast() 方法内设置断点,观察消息是否被正确转发。
2. 验证同事类状态:
  • 使用 ​内存窗口 检查 User 对象的 mediator_ 指针是否指向有效中介者。

性能优化

1.​异步消息处理:
#include <future>  
void ChatRoom::broadcast(const std::string& msg, const User* sender) {  
    std::async(std::launch::async, [=] {  
        for (auto& user : users_) {  
            if (user.get() != sender) {  
                user->receive(msg);  
            }  
        }  
    });  
}  
2. 职责拆分:
  • 将不同交互类型(如日志、权限)拆分到多个中介者子类中。