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

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

什么是中介者模式?

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

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

中介者模式-1.png

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

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

中介者模式-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>

最终效果如下:

中介者模式-示例-1.png
中介者模式-示例-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.mzph.cn/diannao/2631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

93页 | 数据中台标准技术体系方案(免费下载)

【1】关注本公众号&#xff0c;转发当前文章到微信朋友圈 【2】私信发送 数据中台标准技术体系方案 【3】获取本方案PDF下载链接&#xff0c;直接下载即可。 如需下载本方案PPT原格式&#xff0c;请加入微信扫描以下方案驿站知识星球&#xff0c;获取上万份PPT解决方案&#…

文件上传漏洞-白名单检测

如何确认是否是白名单检测 上传一张图片与上传一个自己构造的后缀&#xff0c;如果只能上传图片不能上传其它后缀文件&#xff0c;说明是白名单检测。 绕过技巧 可以利用 00 截断的方式进行绕过&#xff0c;包括 %00 截断与 0x00 截断。除此之外如果网站存在文件包含漏洞&…

ElasticSearch总结二

正向索引和倒排索引&#xff1a; 正向索引&#xff1a; 比方说我这里有一张数据库表&#xff0c;那我们知道对于数据库它一般情况下都会基于i d去创建一个索引&#xff0c;然后形成一个b树。 那么你根据i d进行检索的速度&#xff0c;就会非常的快&#xff0c;那么这种方式的…

智慧水生态系统的架构设计与优化:内蒙古硕达智水百数低代码平台的实践

随着业务的不断扩展&#xff0c;传统的项目管理方式已无法满足现代水生态项目的需求。为提高项目管理和决策效率&#xff0c;内蒙古硕达智水生态科技决定引入百数作为其数字化转型的合作伙伴。 内蒙古硕达智水生态科技有限公司&#xff1a; 内蒙古硕达智水生态科技有限公司&a…

用于割草机器人,商用服务型机器人的陀螺仪

介绍一款EPSON推出适用于割草机器人&#xff0c;商用服务型机器人的高精度陀螺仪模组GGPM61&#xff0c;具体型号为GGPM61-C01。模组GGPM61是一款基于QMEMS传感器的低成本航向角输出的传感器模组&#xff0c;它可以输出加速度、角速度及姿态角等信息&#xff0c;为控制机器人运…

人工智能基础-Python之Pandas库教程

文章目录 前言一、Pandas是什么&#xff1f;二、使用步骤1.引入库2.数据读取2.1 数据类型2.2 数据读取1.常见操作2.txt读取 3.pandas的数据结构3.1 Series1.属性2.创建Series3.查询 3.2 DataFrame1.创建DataFrame 4.查询数据4.1 data.loc 根据行列标签值进行查询1.使用单个labe…

ASP.NET Core 3 高级编程(第8版) 学习笔记 04

第 19 章主要介绍 Restful Service 的相关知识。Restful Service 的核心内容是&#xff1a;&#xff08;1&#xff09;HTTP 请求或 HTTP 动词&#xff0c;用 HTTP 请求表达不同的操作&#xff0c;最好遵守惯例。&#xff08;2&#xff09;资源&#xff0c;通过 PATH 结合 paylo…

stm32f4单片机强制类型转换为float程序跑飞问题

如题&#xff0c;在一个数据解析函数中使用了*(float *)&data[offset]&#xff0c;其中data为uint8类型指针&#xff0c;指向的value地址为 可以看到地址0x20013A31非对齐&#xff0c;最终在执行VLDR指令时导致跑飞 VLDR需要使用对齐访问 跑飞后查看SCB寄存器发现确实是非…

【网络安全】在网络中如何对报文和发送实体进行鉴别?

目录 1、报文鉴别 &#xff08;1&#xff09;使用数字签名进行鉴别 &#xff08;2&#xff09;密码散列函数 &#xff08;3&#xff09;报文鉴别码 2、实体鉴别 鉴别(authentication) 是网络安全中一个很重要的问题。 一是要鉴别发信者&#xff0c;即验证通信的对方的确是…

微博评论爬取

import requests import csv# 打开CSV文件以写入数据 f open(data.csv, modea, encodingutf-8-sig, newline) csv_writer csv.DictWriter(f, fieldnames[昵称, 性别, 归属地, 内容]) csv_writer.writeheader()# 定义一个函数用于获取评论内容 def GetContent(max_id):# 设置请…

【Harmony3.1/4.0】笔记五

概念 本文综合row&#xff0c;column作为主要布局&#xff0c;结合image组件&#xff0c;text组件&#xff0c;textimput组件&#xff0c;button组件以及轮播布局搭建登录页面 效果图 ArkTS代码 //登录综合页面 Entry Component struct Five{//添加图片State imgs:Resource[…

企业有哪些常见网络需求场景?

企业的网络场景需求多种多样&#xff0c;主要取决于其业务规模、运营模式、技术应用等因素。 常见的企业网络场景需求 办公网络需求&#xff1a; 高速稳定的内部网络连接&#xff0c;以支持员工日常办公、数据传输和资源共享。 无线办公网络覆盖&#xff0c;以便员工在会议室…

【LeetCode刷题记录】19. 删除链表的倒数第 N 个结点

19 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出…

大模型的实践应用22-谷歌Gemma AI大模型的架构原理,以及Gemma模型的部署安装本地教程

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用22-谷歌Gemma AI大模型的架构原理,以及Gemma模型的部署安装本地教程。谷歌Gemma AI大模型是由Google AI团队开发并开源。Gemma模型采用Transformer编码器-解码器架构,并加入了一些改进,例如使用稀疏注意力机制来提高推…

世媒讯提供海内外媒体宣发服务,引领企业新媒体发展之路

在这个信息化的时代&#xff0c;软文发稿已经成为企业发展不可或缺的重要工具。随着社会的快速发展&#xff0c;消费者需要更多定制化、个性化的信息。利用软性推广&#xff0c;凭借其细致入微的信息传递&#xff0c;可以迅速抓住消费者的注意力&#xff0c;从而进一步推动企业…

“五之链”第十六期沙龙活动在呆马科技成功举办

2024年4月19日&#xff0c;由临沂呆码区块链网络科技有限公司&#xff08;呆马科技&#xff09;承办的第十六期“五之链”物流主题沙龙活动成功举办。此次活动邀请了政府相关部门、知名科研院所、物流企业等20余家单位参与&#xff0c;共同探讨物流数据要素流通与智能应用的发展…

使用prompt_toolkit构建交互式命令行工具

prompt_toolkit是一个python库&#xff0c;用于构建命令行工具和终端应用。其官网介绍如下&#xff0c; prompt_toolkit is a library for building powerful interactive command line and terminal applications in Python. 安装命令如下&#xff0c; pip install prompt_to…

朴素贝叶斯算法分类

def loadDataSet():postingList[[my, dog, has, flea, problems, help, please], #切分的词条[maybe, not, take, him, to, dog, park, stupid],[my, dalmation, is, so, cute, I, love, him],[stop, posting, stupid, worthless, garbage],[mr, licks, ate, my, steak, …

HarmonyOS开发案例:【相机开发】

基本概念 相机是OpenHarmony多媒体进程提供的服务之一&#xff0c;提供了相机的录像、预览、拍照功能&#xff0c;支持多用户并发取流。 在进行应用的开发前&#xff0c;开发者应了解以下基本概念&#xff1a; 视频帧 视频流指的是将一系列图片数据按照固定时间间隔排列形成的…

2024新算法爱情进化算法(LEA)和经典灰狼优化器(GWO)进行无人机三维路径规划设计实验

简介&#xff1a; 2024新算法爱情进化算法&#xff08;LEA&#xff09;和经典灰狼优化器&#xff08;GWO&#xff09;进行无人机三维路径规划设计实验。 无人机三维路径规划的重要意义在于确保飞行安全、优化飞行路线以节省时间和能源消耗&#xff0c;并使无人机能够适应复杂环…