在复杂的前端交互里,多个UI组件往往彼此依赖:一个输入框变化要禁用按钮,另一个下拉框选中要清空提示。如果让组件直接互相引用并调用方法,依赖关系会迅速膨胀。中介者模式提供一种中心调度思路,所有组件只跟中介者通信,由中介者决定谁该更新。下面用具体代码说明它的实现方式与实际价值。

什么是中介者模式
中介者模式属于行为型设计模式,它定义一个中介对象来封装一系列对象之间的交互。原本对象之间需要互相知道对方的存在,现在它们只认识中介者。这样可以减少对象之间的直接依赖,把多对多通信变成一对多通信。
在JavaScript中,由于没有严格的接口约束,中介者通常就是一个普通对象或者类实例,内部维护参与者的引用,并提供通知与处理方法。参与者通过调用中介者的特定方法来表达意图,而不是直接操作其他参与者。这种方式让交互规则集中在中介者内部,便于阅读和修改。
为什么需要中介者
假设页面有三个控件:用户名输入框、密码输入框和提交按钮。按传统写法,用户名输入框要监听密码输入框的值来决定按钮状态,密码框也要反过来影响用户框提示。这种网状调用会让任何一个控件的逻辑都掺杂着别人的规则。
中介者的作用正是切断这种网。控件只负责发出“我变化了”的消息,中介者收到后统一判断按钮是否可点、提示如何显示。当产品经理想改校验顺序,你只需调整中介者的方法,不用翻遍每个控件的事件回调。对于中大型单页应用,这种集中控制显著降低维护成本。
JS实现中介者模式示例
下面用一个最简表单场景演示。我们创建三个组件对象,再创建一个FormMediator来协调它们。组件不直接引用彼此,而是通过mediator.notify传递自身类型和数据。
// 参与者:用户名输入框
function UserInput(mediator) {
this.mediator = mediator;
this.value = '';
}
UserInput.prototype.change = function(val) {
this.value = val;
// 只通知中介者,不直接碰按钮
this.mediator.notify('user', this.value);
};
// 参与者:密码输入框
function PwdInput(mediator) {
this.mediator = mediator;
this.value = '';
}
PwdInput.prototype.change = function(val) {
this.value = val;
this.mediator.notify('pwd', this.value);
};
// 参与者:提交按钮
function SubmitBtn(mediator) {
this.mediator = mediator;
this.disabled = true;
}
SubmitBtn.prototype.update = function(state) {
this.disabled = !state;
console.log('按钮可用状态:' + (!this.disabled));
};
// 中介者
function FormMediator() {
this.user = new UserInput(this);
this.pwd = new PwdInput(this);
this.btn = new SubmitBtn(this);
}
FormMediator.prototype.notify = function(type, val) {
if (type === 'user') {
this.user.value = val;
} else if (type === 'pwd') {
this.pwd.value = val;
}
// 集中判断规则
var ok = this.user.value.length > 0 && this.pwd.value.length >= 6;
this.btn.update(ok);
};
// 使用
var form = new FormMediator();
form.user.change('tom');
form.pwd.change('123456');
在上面代码中,UserInput和PwdInput完全不知道SubmitBtn的存在。它们变化后只调用mediator.notify。FormMediator根据当前缓存的两个值计算按钮状态,再调用btn.update。这就是典型的中介者结构。
如果后续要加入“邮箱输入框”,只需新增EmailInput类并在 mediator 里增加一段判断,原有两个输入框的代码无需改动。这种扩展性在直接耦合写法里很难做到,因为你要去每个输入框的事件里加邮箱判断。
用事件机制简化中介者
原生JS或框架里常用事件中心充当中介者。下面的例子用一个简单的事件对象代替显式类引用,组件向中心发事件,中心统一处理。
// 简易事件中介者
var eventMediator = {
handlers: {},
on: function(name, fn) {
this.handlers[name] = fn;
},
emit: function(name, data) {
if (this.handlers[name]) {
this.handlers[name](data);
}
}
};
// 组件A
eventMediator.on('a-change', function(v) {
console.log('A发出:' + v);
eventMediator.emit('check', v);
});
// 组件B
eventMediator.on('check', function(v) {
console.log('B收到检查:' + v);
});
eventMediator.emit('a-change', 'hello');
事件中介者把“谁监听谁”变成“谁订阅什么主题”,进一步弱化对象间关系。但也要注意,事件名散落在各处,若没有规范容易引发未知触发。因此中介者内部最好有清晰的命名与文档。
对比直接调用,事件式中介者更适合解耦独立模块;而类式中介者更适合强业务规则的表单场景。两者本质都是把交互逻辑上收,不让组件互相指手画脚。
中介者的优缺点
优点非常明显:降低耦合度,把复杂交互集中管理,新增参与者或规则时影响面小。调试时也能在中介者处打断点,一眼看清消息流。
缺点是中介者自身可能变得庞大,成为“上帝对象”。如果所有逻辑都堆在里面,反而难读。另外每次交互都经过中转,极端高频场景下有一点点性能损耗。实际项目中应只把真正需要协调的逻辑放进去,简单一对一通信没必要强行套用。
总结
JS实现中介者模式并不复杂,核心是让对象通过中心节点沟通。中介者作用在于把网状依赖拍平为星状依赖,提升代码可维护性。写表单、画布工具或多模块面板时,它是不错的选择。只要控制好中介者体积,就能稳稳享受解耦带来的好处。
中介者模式JavaScript设计模式对象解耦修改时间:2026-08-04 11:18:31