中介者模式通过引入中间人对象解耦模块交互,结合消息总线和命令模式可构建高解耦系统。1. 中介者使模块间通信不需直接依赖,仅与中介者交互;2. 消息总线作为中介者实现,统一消息接口并支持广播机制;3. 命令模式封装请求为对象,便于参数化和异步处理;4. 三者协作时,模块通过消息总线发送命令,监听者响应执行,实现灵活扩展;5. 注意避免中介者过度集中、合理划分消息粒度、管理监听器生命周期及考虑同步/异步机制。

在C++项目中,模块之间的依赖关系如果处理不好,很容易导致代码难以维护、扩展和测试。中介者模式(Mediator Pattern)正是用来解耦模块之间直接通信的一种设计模式。当它与消息总线(Message Bus)以及命令模式(Command Pattern)结合使用时,可以构建出一个高度解耦、结构清晰的系统架构。

什么是中介者模式?
中介者模式的核心思想是引入一个“中间人”对象,负责协调多个模块之间的交互。原本需要彼此了解并直接调用的模块,现在只需要通过中介者进行通信,从而大大降低它们之间的耦合度。

举个简单的例子:在一个UI系统中,按钮点击后可能会影响文本框的内容、图表的更新等多个部分。如果不使用中介者,这些组件之间就会形成复杂的网状依赖。而有了中介者之后,按钮只需通知中介者发生了点击事件,由中介者决定如何通知其他组件。
立即学习“C++免费学习笔记(深入)”;
消息总线:统一的消息分发机制
消息总线(Message Bus)是一种常见的中介者实现方式,它作为全局或局部的消息中心,接收来自各个模块的消息,并将这些消息广播给注册过的监听者。

-
优点:
- 所有模块通过统一接口发送和接收消息。
- 发送方无需知道接收方是谁,甚至可以有多个接收方。
- 易于扩展新的消息类型和监听逻辑。
例如,在C++中可以用一个MessageBus类来实现:
class MessageBus {
public:
using Handler = std::function;
void registerHandler(MessageType type, Handler handler) {
handlers[type].push_back(handler);
}
void sendMessage(const Message& message) {
auto it = handlers.find(message.type);
if (it != handlers.end()) {
for (auto& handler : it->second) {
handler(message);
}
}
}
private:
std::map> handlers;
}; 模块A只需调用messageBus.sendMessage(...),模块B则通过注册回调函数监听特定类型的消息即可。
命令模式:封装行为为对象
命令模式(Command Pattern)允许我们将请求封装成独立的对象,这使得我们可以对操作进行参数化、排队、记录日志等操作。它非常适合与中介者一起使用,特别是在处理用户输入或异步任务时。
-
典型结构包括:
- 命令接口(如
execute()) - 具体命令类(实现具体操作)
- 调用者(触发命令执行)
- 接收者(真正执行动作的对象)
- 命令接口(如
例如,我们可以通过命令模式封装一个“保存文件”的行为,然后通过中介者将这个命令发布出去,让合适的模块去执行。
中介者 + 消息总线 + 命令模式:三者协作示例
假设你正在开发一个图形编辑器,里面有菜单项、工具栏按钮、快捷键等多个入口都可以触发“撤销”操作。
- 快捷键模块捕获到Ctrl+Z,生成一个
UndoCommand对象。 - 它通过消息总线发送一条“UndoRequested”消息。
- 编辑器核心模块监听到该消息后,取出命令并执行
command->execute()。 - 执行完成后,也可能再通过消息总线广播“DocumentChanged”消息,通知界面刷新。
这样做的好处是:
- 快捷键模块完全不知道谁会响应撤销操作。
- 界面元素不需要关心底层实现细节。
- 新增功能时只需注册新命令和监听器,不影响已有代码。
实现建议与注意事项
- 避免过度集中化:虽然中介者简化了通信,但不要让它变成“上帝对象”,否则反而成为新的维护瓶颈。
- 合理划分消息粒度:消息不要太泛(比如“Update”),也不要太细碎(每个小变化都发消息),要兼顾灵活性和性能。
- 注意生命周期管理:注册的回调或监听器要注意在对象销毁时及时注销,避免空指针或野指针问题。
- 考虑同步/异步机制:根据需求选择是否在消息总线中支持异步处理,比如使用队列+工作线程。
基本上就这些。把中介者模式用好,再加上消息总线和命令模式的配合,可以在大型C++项目中有效控制模块间的耦合度,提升系统的可维护性和可测试性。










