什么是中介者模式?它解决什么问题?
简化版
中介者模式是一种行为型设计模式,用一个中介者对象封装多个对象之间的交互关系。它主要解决对象之间互相调用、依赖网状膨胀、改一个对象牵动一堆对象的问题。
详细版
中介者模式的核心是:对象之间不再直接互相沟通,而是通过中介者统一协调。
没有中介者时,多个对象之间可能是这样的:
- A 调 B、C、D;
- B 又调 A、C;
- C 再调 A、D;
- 每加一个新对象,都可能要改很多老对象。
引入中介者后,对象只依赖中介者:
- 同事对象只把事件告诉中介者;
- 中介者根据业务规则通知其他对象;
- 对象之间不需要知道彼此存在。
面试里可以这样回答:中介者模式把“多对象之间的复杂交互”集中到一个中介者中管理,让各对象从网状依赖变成星型依赖,降低对象之间的耦合。
完整版教学
一、中介者模式到底在解决哪类复杂度
很多代码一开始并不复杂,只有两个对象互相调用,看起来没问题:
button.onClick() -> input.validate()
但随着业务增长,对象会越来越多:
- 按钮点击后要校验输入框;
- 输入框变化后要控制按钮状态;
- 下拉框变化后要刷新表格;
- 表格选中后要更新详情面板;
- 权限变化后还要影响按钮、菜单和输入框。
如果每个对象都直接知道其他对象,依赖关系会变成一张网。网状依赖最大的问题不是“代码多”,而是“变化扩散”。某个交互规则变了,可能要修改多个对象。
中介者模式就是为这种场景准备的:把交互规则从对象内部抽出来,交给一个专门的协调者。
二、为什么叫“中介者”
它和现实里的中介很像。
比如租房:
- 房东不需要逐个联系所有租客;
- 租客也不需要逐个联系所有房东;
- 双方通过中介传递需求、匹配规则、协调结果。
在代码里:
- 同事对象不直接互调;
- 中介者知道有哪些同事对象;
- 某个对象发生变化时,中介者决定谁应该被通知、执行什么动作。
所以中介者模式不是简单加一层代理,而是把多对象协作规则集中起来。
三、中介者模式的典型结构
中介者模式通常包含三类角色:
- Mediator,中介者接口:定义同事对象和中介者之间的通信入口;
- ConcreteMediator,具体中介者:保存多个同事对象引用,负责协调它们;
- Colleague,同事对象:业务组件本身,只把事件交给中介者,不直接操作其他同事对象。
一个简化结构可以这样理解:
ColleagueA \
ColleagueB -> Mediator -> 根据规则协调其他 Colleague
ColleagueC /
关键变化是:同事对象之间的直接箭头减少了,复杂交互被收敛到中介者。
四、中介者模式不等于“所有逻辑都塞进一个类”
这是一个很常见的误区。
中介者应该管理“对象之间的协作规则”,而不是吞掉每个对象自己的业务能力。
比如聊天室里:
- 用户对象负责发送消息、接收消息;
- 聊天室中介者负责把某个用户的消息转发给其他用户;
- 用户如何展示消息,不应该塞进聊天室中介者;
- 消息如何持久化,也不一定属于中介者本身。
如果把所有细节都放进中介者,中介者会变成上帝类。正确做法是让中介者只负责协调,具体业务仍留在合适的对象或服务里。
五、面试中怎么判断是否该使用中介者模式
可以从三个信号判断:
- 多个对象之间存在复杂交互;
- 对象之间互相持有引用,形成网状依赖;
- 交互规则经常变化,而单个对象自身职责相对稳定。
如果只是两个对象简单调用,用中介者反而会绕。
如果对象数量多、交互规则集中变化,中介者就有价值。
六、常见误区与追问
中介者模式用一个协调对象封装多个同事之间的交互,使同事不再直接互相引用。4个组件两两交互最多有6条关系,改为各自连接 Mediator 后约4条;新增组件也只需接入协调协议。它减少依赖传播,但交互规则仍需被正确建模。
| 检查维度 | 判定依据 |
|---|---|
| 原始问题 | 同事之间形成网状依赖 |
| 核心手段 | 把跨对象交互集中到 Mediator |
C1,C2,C3,C4 -> Mediator -> coordinated actions
记忆钩子:把网状沟通收敛成星形沟通。
- 误区:中介者等同于全局事件总线。 经典中介者常显式协调特定同事,事件总线侧重发布订阅传输。
- 追问:为什么属于行为型模式? 它定义多个对象如何协作和传递行为。
- 误区:有中介者后同事不需要任何业务逻辑。 同事保留自身职责,中介者只处理跨对象协调。
- 追问:它与迪米特法则有什么关系? 同事减少对其他具体对象的了解,有助于降低知识范围。
- 追问:最大风险是什么? 所有协调逻辑集中后,中介者可能变成难维护的上帝对象。
七、加强记忆
中介者模式的核心不是“多加一个中间层”,而是把多对象之间的网状交互收敛成由中介者统一协调的星型结构。它让同事对象只关心自己和中介者,不再直接依赖彼此,适合处理 UI 组件联动、聊天室、流程协调、模块交互等复杂协作场景。