【设计模式】使用中介者模式优化表单交互

news/2024/11/21 1:31:34/

我们想象一下机场的指挥塔,如果没有指挥塔的存在,每一架飞机要和方圆 100 公里内的所有飞机通信,才能确定航线以及飞行状况,后果是不可想象的。现实中的情况是,每架飞机都只需要和指挥塔通信。指挥塔作为调停者,知道每一架飞机的飞行状况,所以它可以安排所有飞机的起降时间,及时做出航线调整。

什么是中介者模式

在程序里,也许一个对象会和其他 10 个对象打交道,所以它会保持 10 个对象的引用,并且自己维护与其他对象的交互逻辑。

当程序的规模增大,对象会越来越多,它们之间的关系也越来越复杂,难免会形成网状的交叉引用。

<a class=中介者模式-1.png" />

中介者模式的作用就是解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用所以当一个对象发生改变时,只需要通知中介者对象即可。

中介者模式里,对象之间几乎不知道彼此的存在,它们只能通过中介者对象来互相影响对方。

<a class=中介者模式-2.png" />

中介者模式使各个对象之间得以解耦,以中介者和对象之间的一对多关系取代了对象之间的网状多对多关系。

各个对象只需关注自身功能的实现,对象之间的交互关系交给了中介者对象来实现和维护。

示例:要素之间相互影响的商品表单

假设一个商品选择表单有如下功能:

  • 剩余数量受所选颜色和内存影响。
  • 购买数量超过剩余数量时提交按钮置灰。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><form id="form"><div><label for="color">颜色</label><select name="color" id="color"><option value="red">red</option><option value="blue">blue</option><option value="green">green</option></select></div><div><label for="memory">内存</label><select name="memory" id="memory"><option value="red">2G</option><option value="blue">4G</option><option value="green">8G</option></select></div><div><label for="num">购买数量</label><input name="num" type="number" id="num" /></div><div><span>剩余数量:</span><span id="surplus"></span></div><button id="btn">提交</button></form><script>const form = document.getElementById("form");const numInput = form.num;const colorSelect = form.color;const colorMemory = form.memory;const btn = form.btn;const surplus = document.getElementById("surplus");// 根据参数获取剩余数量const commodityMap = {};function getCommodityNum(color, memory) {const key = `${color}-${memory}`;if (!commodityMap[key]) {commodityMap[key] = Math.floor(Math.random() * 10);}return commodityMap[key];}// 更新剩余数量function updateSurplus() {const num = getCommodityNum(colorSelect.value, colorMemory.value);surplus.innerText = num;}// 更新按钮状态function updateBtnDisabledStatus() {if (Number(surplus.innerText) < Number(numInput.value)) {btn.setAttribute("disabled", true);} else {btn.removeAttribute("disabled");}}numInput.oninput = function () {updateBtnDisabledStatus();};colorSelect.onchange = function () {updateSurplus();updateBtnDisabledStatus();};colorMemory.onchange = function () {updateSurplus();updateBtnDisabledStatus();};btn.onclick = function (e) {const params = {num: numInput.value,color: colorSelect.value,memory: colorMemory.value,};console.log(params);e.preventDefault();};updateSurplus();</script></body>
</html>

最终效果如下:

<a class=中介者模式-示例-1.png" />
<a class=中介者模式-示例-2.png" />

这样的实现方式,需要在每一个表单项的 onchange 事件中维护两种事件:更新按钮状态更新剩余数量

这种写法的弊端在于需要牢记每个表单项之间的关联关系,在后续有变更的情况下要在多处进行修改,同时也产生了一些重复代码。

如果后续需求变动,要再加一个 cpu 的选择,那就要将 onchange 事件处理程序再粘贴一份出来:

// ...
cpuSelect.onchange = function () {updateSurplus();updateBtnDisabledStatus();
};
// ...

中介者模式优化

引入一个中介者类来集中定义处理程序。

// ...
class Mediator {static change(target) {updateBtnDisabledStatus();if (target != numInput) {updateSurplusText();}}
}// ...
numInput.oninput = function () {Mediator.change(this);
};colorSelect.onchange = function () {Mediator.change(this);
};colorMemory.onchange = function () {Mediator.change(this);
};
// ...

这样改动之后,不需要再在表单项的 onchange 事件中处理 更新按钮状态更新剩余数量,而是只触发 Mediator.change 方法。

Mediator.change 方法中根据触发事件的对象来区分要执行什么操作。

这时如果要加一个 cpu 选择,可以添加如下代码:

// ...
cpuSelect.onchange = function () {Mediator.change(this);
};
// ...

可以看到这样的改动对于整体而言改动较小,并且 cpuSelect 对象不需要关注它的改动会造成什么影响。

总结

中介者模式的优点是解除了对象之间的紧密耦合关系,在新建对象以及新建对象关系时提供更高的可维护性和可扩展性。

它的缺点在于它将对象之间交互的复杂性转移成了中介者对象的复杂性,使得中介者对象经常是巨大的,中介者对象自身往往就是一个难以维护的对象

是否使用中介者模式取决于对象之间的耦合程度,毕竟我们写程序是为了快速完成项目交付生产,而不是堆砌模式和过度设计。

参考

《JavaScript 设计模式与开发实践》


http://www.ppmy.cn/news/1439779.html

相关文章

js实现字符串转json对象的四种方法

在JavaScript中&#xff0c;将字符串转换为JSON对象通常使用的是JSON.parse()方法。但为了满足你的需求&#xff0c;我将提供四种方法&#xff0c;虽然其中大部分方法都是基于JSON.parse()。 方法一&#xff1a;使用JSON.parse() JSON.parse()是最常用且最标准的方法&#xf…

OV SSL证书申请指南——六步轻松搞定

OV证书的申请流程如下&#xff1a; 一 确定申请渠道 根据自己的品牌偏好&#xff0c;选择一个证书服务商&#xff0c;这里推荐JoySSL,作为国产服务商&#xff0c;除了提供Digicert、Sectigo、Geotrust、Globalsign等国际品牌证书外&#xff0c;还拥有自主品牌OV证书。在JoySSL…

分类与预测算法评价的介绍

分类与预测算法的评价是在机器学习中至关重要的一步&#xff0c;它帮助我们了解模型在解决特定问题上的表现如何&#xff0c;并且可以帮助我们选择最适合我们需求的算法。下面是分类与预测算法评价的一般介绍&#xff1a; 分类与预测问题 分类问题&#xff1a;是指将数据分为预…

《HCIP-openEuler实验指导手册》1.5 Apache持久化连接配置

一、知识点 二、配置方法 在/etc/httpd/conf.d目录中创建持久连接相关配置文件keepalived.conf&#xff0c;并添加如下配置信息&#xff1a; KeepAlive On KeepAliveTimeout 20 MaxKeepAliveRequests 500

【Redis | 第十篇】Redis与MySQL保证数据一致性(两种解决思路)

文章目录 10.Redis和MySQL如何保证数据一致性10.1双写一致性问题10.2数据高度一致性10.3数据同步允许延时10.3.1中间件通知10.3.2延迟双删 10.Redis和MySQL如何保证数据一致性 10.1双写一致性问题 Redis作为缓存&#xff0c;它是如何与MySQL的数据保持同步的呢&#xff1f;特…

git提交常用

git config --global user.name "你的名字或昵称" git config --global user.email "你的邮箱" 第一次上传到码云 1.找到要提交到码云的文件夹 右击打开Git Bash Here 2.用命令行创建本地仓库 git init 3.将待全部文件放入缓冲区 git add . 4.提交缓…

服务器(AIX、Linux、UNIX)性能监视器工具【nmon】使用介绍

目录 ■nmon简介 1.安装 2.使用简介 3.使用&#xff08;具体使用的例子【CPU】【内存】&#xff09; 4.采集数据 5.查看log&#xff08;根据结果&#xff0c;生成报表&#xff09; 6.分析结果 7.设定任务计划&#xff08;Cron&#xff09;&#xff0c;每日执行 ■nmo…

【算法基础实验】图论-基于DFS的连通性检测

基于DFS的连通性检测 理论基础 在图论中&#xff0c;连通分量是无向图的一个重要概念&#xff0c;特别是在处理图的结构和解析图的组成时。连通分组件表示图中的一个子图&#xff0c;在这个子图中任意两个顶点都是连通的&#xff0c;即存在一条路径可以从一个顶点到达另一个顶…