中介者模式的核心是让对象只依赖中介者而不直接互相引用,通过 notify() 等接口通信,中介者用 weak_ptr 管理同事生命周期,聚焦事件转发而非业务逻辑,避免循环引用与上帝类。

中介者模式的核心是让对象只依赖中介者,不直接互相引用
直接让两个类 A 和 B 互相持有对方指针,修改一个就得改另一个头文件、重新编译,耦合度高得离谱。中介者模式把交互逻辑抽出来,变成一个独立的 Mediator 类,A 和 B 都只和它通信——不是“谁调谁”,而是“都找中间人办事”。关键在于:所有通信必须通过 notify() 或类似接口触发,且中介者内部用弱引用(如 std::weak_ptr)或裸指针管理同事对象,避免循环引用或生命周期问题。
用 std::shared_ptr + std::weak_ptr 管理同事生命周期
同事对象(如 ColleagueA、ColleagueB)通常由外部创建并托管在 std::shared_ptr 中,中介者用 std::weak_ptr 持有它们。这样既能在需要时安全访问,又不会延长对象寿命。常见错误是直接存 std::shared_ptr,导致中介者和同事互相持有时无法析构。
- 中介者构造时不接管所有权,只接收
std::weak_ptr参数 - 每次调用前用
lock()判断是否还活着:if (auto ptr = colleague.lock()) { /* 安全使用 */ } - 同事类里不要保存中介者的
shared_ptr,否则容易形成环;改用裸指针或std::weak_ptr(如果中介者本身也是动态分配)
Mediator 接口设计要聚焦“事件通知”,别塞业务逻辑
中介者不该是万能胶水,更不是第二个上帝类。它的职责仅限于转发、协调、简单路由。比如 UI 控件联动:按钮点击后通知中介者,中介者决定是否禁用输入框、更新标签文本——但“禁用”“更新”这些操作仍由控件自己完成,中介者只发指令,不越界调用控件私有方法。
- 接口函数命名体现意图,如
onButtonClicked()、onDataReceived(const std::string&),而不是泛泛的handleEvent(int type, void* data) - 避免在中介者里写 if-else 判断具体同事类型;用多态或 visitor 模式解耦判断逻辑
- 若同事行为差异大,考虑把部分策略外移到独立的
Strategy类,中介者只持有策略指针
实际写法中容易漏掉线程安全和空指针检查
中介者常被多个线程调用(比如网络回调、定时器、GUI 事件),而同事对象可能在某时刻被销毁。这时候 weak_ptr::lock() 返回空是常态,不是异常。很多实现直接解引用导致崩溃,或者加锁粒度过大拖慢性能。
立即学习“C++免费学习笔记(深入)”;
- 对每个
weak_ptr单独lock(),不要先统一 lock 再批量操作 - 若需原子性协调多个同事,用
std::shared_ptr临时延长其生命周期(auto a = a_ptr.lock(); auto b = b_ptr.lock(); if (a && b) { ... }) - 避免在中介者里用
std::mutex锁整个notify()函数;优先用无锁结构(如std::atomic标志位)或细粒度锁
真正难的不是写个 Mediator 类,而是判断哪些交互该放进中介者、哪些该留在对象内部——边界模糊时,先写测试用例,看改动一个同事是否波及三个以上其他类,再决定是否引入中介者。


















