中介者模式的核心是通信解耦而非类设计,C++中关键在于引用持有、交互触发与通信可替换性;应通过接口抽象和shared_ptr避免循环依赖,用具名方法替代泛型notify提升可维护性。

中介者模式的核心不是类,而是通信解耦的思路
直接写 Mediator 类容易陷入“为模式而模式”的陷阱。C++ 中真正关键的是:**谁持有对其他组件的引用?谁触发交互逻辑?通信是否可被替换或测试?** 不是套模板,而是把原本散落在 Colleague 之间硬编码的 if-else 或直接调用,收归到一个可控的中间层里。
用 std::shared_ptr + 接口抽象避免循环依赖
两个同事类(比如 Button 和 TextBox)如果互相持有对方指针,头文件就得相互 #include,极易引发编译错误或隐式依赖。正确做法是:
- 定义纯虚接口(如
class UIControl),让具体控件继承它 - 中介者只持有一个
std::vector<:shared_ptr>></:shared_ptr>或按类型索引的std::map<:string std::weak_ptr>></:string> - 所有控件通过
setMediator(std::shared_ptr<mediator> m)</mediator>注册自己,而非在构造时传入具体同事类型
这样 Button.h 不需要知道 TextBox 的存在,编译隔离性立刻提升。
notify() 调用时机决定行为是否可预测
很多初学者在 Button::onClick() 里直接调用 mediator->handle("button_clicked"),但问题在于:这个通知是同步阻塞的,且无法区分“谁发的”和“发给谁”。更稳健的做法是:
立即学习“C++免费学习笔记(深入)”;
- 让
notify()接收发送者指针(const UIControl*)和事件枚举(如enum class Event { Clicked, TextChanged }) - 中介者内部用
switch或策略映射表分发,例如:if (event == Event::Clicked && sender == buttonA) { textBoxB->clear(); } - 避免在
notify()内部做耗时操作;必要时转成异步消息队列(如用std::queue+processQueue())
否则 UI 响应卡顿、重入问题(比如 clear() 又触发 TextChanged)会悄无声息地破坏状态。
别用模板强行泛化 Mediator,先解决具体场景
看到 Python/Java 示例里用泛型 Mediator<t></t> 就想照搬?C++ 模板推导会让调用点变得晦涩,且无法运行时切换策略。实际项目中更常见的是:
- 一个对话框对应一个
DialogMediator,管理其内部 5 个控件 - 一个游戏场景对应一个
GameWorldMediator,协调玩家、NPC、UI HUD - 每个中介者手动写
onPlayerMoved()、onEnemySpotted()等具名方法,比通用notify(Event, void*)更易调试、补全、重构
泛型抽象的价值在复用率 > 3 个相似中介者时才体现;过早模板化只会增加编译时间、隐藏类型错误、让 gdb 调试时看不到实际对象类型。


















