首页/开发/代码质量与评审速查/中介者模式 Mediator(行为型)
设计原则与模式62 条

中介者模式 Mediator(行为型)

把多对多的对象互引用收敛为一对多的中央协调:同事对象只与中介者通信,交互规则集中;中介者负担过重时再拆分领域服务。

把网状交互收成星形

当很多对象需要互相通信时,两两引用会形成数量巨大的依赖:改动一个对象的分支,就要检查所有对手方。中介者模式引入一个中央协调者,同事对象只与中介者通信,交互规则集中在一处,依赖关系从网状变成星形。

基本信息

意图把多对多的互相引用收敛为星形结构
应用界面控件联动、对话框编排、消息路由
近亲事件总线是它的常见演进形态,由中心分发者路由消息
风险中介者膨胀成上帝对象

典型使用场景

  • 表单联动:某个字段变化后,其他字段的启用状态与默认值随之改变
  • 对话框编排:确定与取消按钮、各输入框的校验状态互相制约
  • 调度场景:航班与跑道不直接交互,由塔台统一分配
  • 服务端消息路由:用户之间不直接互连,消息经房间或服务端转发
  • 流程编排:由编排器统一调度多个参与者,参与者之间不直接互相调用

形态示意

形态示意
# 之前:A 与 B、C 两两互知,依赖成网状,改一处要检查所有对手方
# 之后:A -> Mediator -> B/C,依赖线性化
class DialogMediator:
    def input_changed(self, src):        # 统一入口:谁变化了
        if src is self.name_field:
            self.save_button.enabled = bool(self.name_field.text)
            self.hint_label.text = '请填写姓名' if not src.text else ''

收益与代价对照

方面收敛前收敛后
依赖关系参与者之间两两互相引用每个参与者只指向中介者
改交互规则要改多处参与者只改中介者一处
参与者复用耦合于具体对手方只依赖中介接口
主要风险关系散乱难追踪中介者膨胀成上帝对象
中介者与观察者的分工不同:观察者解决一对多通知,订阅者互不相识;中介者解决多对多交互规则,规则由中介者掌握。实际实现常把两者叠加,中介者内部用订阅收集变更事件。
中介者最容易变成上帝对象。可按场景给方法分类(校验类、可见性类、导航类),其中一类超过一定规模就拆成独立的协作对象,让中介者只保留转发与顺序。

易错点

  • 中介者堆满业务分支:几个月后它成为整个模块里最不敢改的文件
  • 为少量交互引入中介者:多一层间接,读代码要跳两次才明白发生了什么
  • 参与者绕过中介者直接互相调用:规则出现两套,行为不一致且难以发现
  • 中介者同时承担数据存储:协调者变成数据源,职责混杂,测试难写

数据来源与参考

  • 《设计模式》(GoF)· Mediator
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌