Skip to content

中介者模式

1. 核心概念与价值

中介者模式将系统的通信模式从**“多对多”简化为“一对多”**。

维度描述形象比喻
核心意图减少对象之间的直接耦合,将复杂的联动逻辑集中管理。机场塔台。飞机之间不直接沟通,全都听塔台指挥。
主要优点1. 极大地降低了类/组件之间的耦合;
2. 交互逻辑集中化,易于维护和修改;
3. 简化了对象的协议。
联合国。各国不直接起冲突,通过联合国调停。
主要缺点中介者对象可能会变得过于庞大和复杂(演变成“上帝对象”),难以维护。过度集权。如果塔台瘫痪,全机场都乱了。

2. 模式结构:从“网状”到“星型”

2.1 传统网状结构(混乱)

A 变了通知 B,B 变了影响 C,C 又可能去改 A。代码里充斥着 this.parent.sibling.child...

2.2 中介者星型结构(清晰)

所有组件(同事类 Colleague)只与 中介者 (Mediator) 交流。中介者收到消息后,决定如何影响其他组件。

3. 代码实现示例:购物下单逻辑

假设一个购买页面,有“颜色选择”、“数量输入”、“剩余库存显示”和“提交按钮”。它们的逻辑高度联动。

js
// 1. 中介者对象
const mediator = (function() {
  // 维护对所有组件的引用
  let colorSelect, numberInput, memorySelect, stockDisplay, submitBtn;

  return {
    // 初始化时注入组件
    setComponents: function({ color, number, memory, stock, button }) {
      colorSelect = color;
      numberInput = number;
      memorySelect = memory;
      stockDisplay = stock;
      submitBtn = button;
    },

    // 核心:所有联动逻辑都在这里!
    changed: function(obj) {
      const color = colorSelect.value;
      const num = numberInput.value;
      const memory = memorySelect.value;
      const stock = stockData[color][memory]; // 假设有库存数据

      if (obj === colorSelect || obj === memorySelect) {
        stockDisplay.innerHTML = stock;
      }

      if (num > stock) {
        submitBtn.disabled = true;
        submitBtn.innerHTML = "库存不足";
      } else {
        submitBtn.disabled = false;
        submitBtn.innerHTML = "加入购物车";
      }
    }
  };
})();

// 2. 组件类(同事类):它们不互相认识,只认识中介者
class Component {
  constructor(name) {
    this.name = name;
    this.value = '';
  }
  change() {
    mediator.changed(this); // 发生变化时,只管告诉中介者
  }
}

// 3. 使用
const colorSel = new Component('color');
const numInp = new Component('number');
// ... 初始化逻辑
mediator.setComponents({ color: colorSel, number: numInp, ... });

4. 模式辨析:中介者 vs 发布-订阅 (Pub-Sub)

这两个模式非常像,都是为了解耦,但重点不同:

特性发布-订阅模式中介者模式
通信方向多向。发布者和订阅者通过调度中心自由交换消息。双向。组件发送消息给中介者,中介者指挥其他组件。
逻辑存储调度中心不处理逻辑,只负责分发。逻辑高度集中。中介者内部包含复杂的业务规则。
解耦程度极高。完全互不相识。较高。但中介者必须了解所有组件的接口。
典型代表Vue 事件总线、Redux。Vuex/Pinia (Actions 逻辑层)

5. 常见问题 (FAQ)

5.1 中介者模式在现代前端(Vue/React)中还有用吗?

  • 答:非常有用,但形式变了。
    • 在传统的组件化开发中,如果你有大量的“父子/兄弟组件”传参和回调,那就是典型的网状结构。
    • Vuex / Redux / Pinia 本质上就是中介者模式的演进。所有的组件状态都在 Store(中介者)中管理,组件只负责触发 Action(发送消息),Store 负责处理逻辑并分发状态更新。

5.2 什么时候不该使用中介者模式?

  • :如果你的系统组件只有 3-5 个,且交互逻辑很简单。强行引入中介者会增加不必要的抽象层,导致代码变得晦涩难懂。“中介者膨胀” 是该模式最危险的后果。

5.3 如何解决中介者对象(Mediator)过大的问题?

  • 分而治之
    • 不要创建一个全局的、管天管地的巨大中介者。
    • 应该根据业务模块,创建多个局部中介者(类似于 Vuex 的 Modules)。每个模块的中介者只负责管理自己领地内的组件交互。

5.4 中介者模式能和观察者模式结合吗?

  • 答:可以,且经常结合。
    • 组件作为“观察者”订阅中介者的消息;中介者监听组件的变动。这种结合能让代码更加灵活。