JavaScript设计模式:中介者模式详解与实战
本文深入解析JavaScript中的中介者模式,通过手机购买页面的示例,展示如何解除对象间的紧耦合。文章对比了直接交互与引入中介者后的代码结构,阐述了迪米特法则的应用,并客观分析了该模式在维护复杂性上的优缺点,为处理复杂对象交互提供重构思路。
中介者模式定义
一、定义
面向对象设计的核心思想之一是将行为分散到不同的对象中,通过细化对象粒度来提升代码的可复用性。然而,当细粒度对象之间的交互关系急剧增加时,这种紧密耦合反而会成为降低可复用性的瓶颈。中介者模式正是为了解决这一问题而存在,其核心作用在于切断对象之间直接的联系,从而实现解耦。
未使用中介者的购买示例
二、示例:购买商品
- 假设我们正在开发一个手机购买页面,用户可以选择手机颜色并输入购买数量,页面需实时展示这些输入内容。此外,页面上还有一个按钮用于动态显示下一步操作:如果所选颜色的库存充足,按钮显示“加入购物车”;否则显示“库存不足”。
<div>
<span>请选择颜色</span>
<select id="selColor">
<option value="roseGold">玫瑰金</option>
<option value="luxuryGold">土豪金</option>
</select>
</div>
<div>
<span>请输入购买数量:</span>
<input type="text" id="selNum" />
</div>
<div>
<span>您选择的颜色为:</span><strong id="conColor"></strong>
<span>您选择的数量为:</span><strong id="conNum"></strong>
</div>
<button id="nextBtn">加入购物车</button>
// 库存量
var goods = {
roseGold: 10,
luxuryGold: 10
};
var colorSelect = document.getElementById("selColor"),
numberInput = document.getElementById("selNum"),
colorInfo = document.getElementById("conColor"),
numberInfo = document.getElementById("conNum"),
nextBtn = document.getElementById("nextBtn");
colorSelect.onchange = function() {
var color = colorSelect.value, // 颜色
number = +numberInput.value, // 数量
stock = goods[color]; // 对应颜色的库存量
colorInfo.innerHTML = color;
if(!color) {
nextBtn.disabled = true;
nextBtn.innerHTML = "请选择手机颜色";
return;
}
if(!number || (((number - 0) | 0) !== (number - 0))) {
nextBtn.disabled = true;
nextBtn.innerHTML = "请选择手机数量";
return;
}
if( number > stock) {
nextBtn.disabled = true;
nextBtn.innerHTML = "库存不足";
return;
}
nextBtn.disabled = false;
nextBtn.innerHTML = "加入购物车";
};
/* 购买数量做同样处理 */
当页面中新增一个代表手机内存的下拉列表框时,原有的代码逻辑需要大幅修改,以处理新增控件与现有逻辑之间的交互,导致改动面很大。
引入中介者后的实现
三、引入中介模式
在中介者模式下,所有节点对象仅与中介者进行通信。当下拉选择框 selColor、selMemory 或文本框 selNum 发生事件时,它们不再直接相互操作,而是通知中介者自身状态已改变,并将自身作为参数传递给中介者。中介者负责识别是哪个对象发生了变化,并处理后续的交互逻辑,从而将复杂的对象间关系集中管理。
<div>
<span>请选择颜色:</span>
<select id="selColor">
<option value="roseGold">玫瑰金</option>
<option value="luxuryGold">土豪金</option>
</select>
</div>
<div>
<span>请选择内存:</span>
<select id="selMemory">
<option value="16G">16G</option>
<option value="64G">64G</option>
</select>
</div>
<div>
<span>请输入购买数量:</span>
<input type="text" id="selNum" />
</div>
<div>
<span>您选择的颜色为:</span><strong id="conColor"></strong>
<span>您选择的内存为:</span><strong id="conMemory"></strong>
<span>您选择的数量为:</span><strong id="conNum"></strong>
</div>
<button id="nextBtn">加入购物车</button>
// 库存量
var goods = {
"roseGold|16G": 10,
"roseGold|32G": 10,
"luxuryGold|16G": 10,
"luxuryGold|32G": 10
};
var colorSelect = document.getElementById("selColor"),
memorySelect = document.getElementById("selMemory"),
numberInput = document.getElementById("selNum"),
colorInfo = document.getElementById("conColor"),
memeryInfo = document.getElementById("conMemory"),
numberInfo = document.getElementById("conNum"),
nextBtn = document.getElementById("nextBtn");
var mediator = (function() {
return {
changed: function(obj) {
var color = colorSelect.value, // 颜色
memory = memorySelect.value,// 内存
number = +numberInput.value, // 数量
stock = goods[color + '|' + memory]; // 对应颜色的库存量
if(obj === colorSelect) {
colorInfo.innerHTML = color;
}else if(obj === memorySelect) {
memeryInfo.innerHTML = memory;
}else if(obj === numberInput) {
numberInfo.innerHTML = number;
}
if(!color) {
nextBtn.disabled = true;
nextBtn.innerHTML = "请选择手机颜色";
return;
}
if(!memory) {
nextBtn.disabled = true;
nextBtn.innerHTML = "请选择手机内存";
return;
}
if(!number || (((number - 0) | 0) !== (number - 0))) {
nextBtn.disabled = true;
nextBtn.innerHTML = "请选择手机数量";
return;
}
if( number > stock) {
nextBtn.disabled = true;
nextBtn.innerHTML = "库存不足";
return;
}
nextBtn.disabled = false;
nextBtn.innerHTML = "加入购物车";
}
};
})();
// 事件函数
colorSelect.onchange = function() {
mediator.changed(this);
};
memorySelect.onchange = function() {
mediator.changed(this);
};
numberInput.oninput = function() {
mediator.changed(this);
}
原理与优缺点分析
中介者模式是迪米特法则(又称最少知识原则)的一种具体实现。该原则主张一个对象应尽可能少地了解其他对象,从而避免“城门失火,殃及鱼池”式的连锁反应,降低系统耦合度。
该模式的主要缺点在于系统中必须引入一个中介对象。由于对象间交互的复杂性被转移到了中介者身上,导致中介者对象往往变得非常庞大且复杂,从而增加了维护和理解的难度。
通常,如果对象间复杂的耦合关系导致调用和维护变得极其困难,且这种耦合度随项目发展呈指数级增长,那么考虑使用中介者模式来重构代码是一个合理的选择。
希望本文所述对大家学习javascript程序设计有所帮助。
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
