中介者模式的优缺点是什么?
简化版
中介者模式的优点是降低对象之间的直接耦合、集中管理协作规则、让同事对象更简单;缺点是中介者容易变复杂,甚至演化成上帝类。它适合交互复杂的对象群,不适合简单调用关系。
详细版
优点:
- 将多对多依赖变成对象到中介者的依赖;
- 同事对象不需要知道彼此,职责更单一;
- 协作规则集中,修改联动逻辑更方便;
- 新增同事对象时,可以减少对已有对象的修改。
缺点:
- 中介者可能承担太多逻辑;
- 交互规则都集中后,中介者代码可能很难维护;
- 简单场景使用会增加不必要的间接层;
- 如果边界设计不好,会把系统复杂度从多个对象转移到一个巨型类。
面试里要强调:中介者模式的价值来自“管理复杂交互”,不是为了让代码看起来更高级。
完整版教学
一、优点一:降低同事对象之间的直接耦合
没有中介者时,对象之间互相调用:
A -> B
A -> C
B -> C
C -> A
这种结构会让每个对象知道太多其他对象。
引入中介者后:
A -> Mediator
B -> Mediator
C -> Mediator
同事对象不直接依赖彼此,依赖关系更清楚。
二、优点二:协作规则集中管理
多对象联动最大的痛点是规则散落。
比如 UI 表单中:
- 输入框变化影响按钮;
- 下拉框变化影响列表;
- 勾选框变化影响提示;
- 权限变化影响多个组件。
如果这些规则散落在各个组件里,排查问题会很痛苦。中介者把这些规则集中到一个地方,维护时更容易找到入口。
三、优点三:同事对象职责更单一
同事对象只需要关心自己的状态和行为。
例如输入框:
- 它负责保存输入值;
- 它负责触发变化事件;
- 它不需要知道按钮、列表、提示框要怎么变。
这符合单一职责原则。
四、缺点一:中介者容易变胖
中介者模式最典型的风险就是中介者变成上帝类。
一开始它只处理几个组件联动,后来不断往里加:
- 权限判断;
- 数据校验;
- 日志记录;
- 异常处理;
- 消息发送;
- 数据持久化。
最后所有逻辑都挤在中介者里,复杂度并没有消失,只是集中爆炸。
正确做法是让中介者只负责协调,把独立能力拆给专门对象。
五、缺点二:简单场景会增加复杂度
如果只是 A 调 B:
a.callB();
硬加中介者:
a.notifyMediator();
mediator.callB();
反而让代码更绕。
设计模式应该用在复杂度已经出现或明确即将出现的地方。简单场景保持直接调用更好。
六、缺点三:集中逻辑可能影响复用
如果中介者绑定了太多具体对象,它本身可能很难复用。
比如一个 OrderPageMediator 同时知道订单表格、优惠券弹窗、支付按钮、库存提示、物流组件,那么它基本只能服务这个页面。
这并不一定是坏事,因为中介者本来就是为一组对象协调而生。但要接受它的复用边界,不要强行把所有中介者做成通用组件。
七、常见误区与追问
中介者用中心复杂度换取外围简单度。6个同事若两两直接依赖,最多15条无向关系;收敛后约6条到中介者的连接,单个同事更易替换和测试。但协调规则会集中,中心故障或错误可能影响整个交互场景。
| 检查维度 | 判定依据 |
|---|---|
| 收益 | 减少同事依赖,交互规则集中可见 |
| 代价 | 中介者膨胀、单点复杂度和调试跳转 |
direct=n(n-1)/2;mediated=n
心法:外围越简单,越要警惕中心是否变成新的泥球。
- 误区:引入中介者后总复杂度一定下降。 复杂度主要被转移和集中,规则本身并未消失。
- 追问:可测试性为何改善? 同事可用假 Mediator 隔离测试,中介者则集中做交互场景测试。
- 误区:中心化一定导致性能瓶颈。 进程内调用通常不明显,但高吞吐异步中心需评估队列和锁。
- 追问:中介者怎样避免单点故障? 分布式场景要做冗余和持久化;进程内对象则关注异常隔离。
- 追问:何时收益不够? 只有2个对象且交互稳定时,直接依赖往往更清晰。
八、加强记忆
中介者模式的优点是解耦同事对象、集中协作规则、让单个对象更简单;缺点是中介者容易膨胀,简单场景会显得绕。它的本质是用一个协调中心管理复杂交互,所以要控制中介者边界,把协调和具体业务能力分清楚。