【前端设计模式】之命令模式
引言
命令设计模式是一种行为型设计模式,它允许你将命令封装到一个对象中,从而使你可以参数化不同的请求,以及存储、排队、重播和撤销请求。这种设计模式在处理用户界面操作、远程网络请求或其他需要异步执行的操作时非常有用。在前端开发中,我们经常需要处理复杂的操作和交互逻辑。命令模式允许我们将操作封装成对象,并将其作为参数传递、存储或记录,从而实现优雅地管理和执行操作。
命令模式的特性
命令模式具有以下特性:
- 命令(Command):封装了一个具体操作及其参数,并提供了执行该操作的方法。
- 接收者(Receiver):负责执行具体操作的对象。
- 调用者(Invoker):负责调用命令对象并触发其执行方法。
- 客户端(Client):创建并配置具体命令对象,并将其传递给调用者进行执行。
- 撤销与重做:通过记录历史命令对象,可以实现撤销和重做操作。
应用示例
在前端开发中,我们可以使用命令模式来解决以下问题,并提供相应的代码示例:
1. 按钮点击事件
在处理按钮点击事件时,命令模式可以帮助我们将具体操作封装成命令对象,并将其与按钮关联起来。
// 定义命令接口
class Command {execute() {throw new Error("execute() method must be implemented");}
}
// 定义具体命令类
class SaveCommand extends Command {constructor(receiver) {super();this.receiver = receiver;}execute() {this.receiver.save();}
}
class DeleteCommand extends Command {constructor(receiver) {super();this.receiver = receiver;}execute() {this.receiver.delete();}
}
// 定义接收者类
class Receiver {save() {console.log("Saving data...");// 执行保存操作的逻辑}delete() {console.log("Deleting data...");// 执行删除操作的逻辑}
}
// 定义调用者类
class Invoker {setCommand(command) {this.command = command;}executeCommand() {this.command.execute();}
}
// 使用示例
const receiver = new Receiver();
const saveCommand = new SaveCommand(receiver);
const deleteCommand = new DeleteCommand(receiver);
const invoker = new Invoker();
invoker.setCommand(saveCommand);
invoker.executeCommand(); // 输出: "Saving data..."
invoker.setCommand(deleteCommand);
invoker.executeCommand(); // 输出: "Deleting data..."
在这个示例中,有四个主要类:Command
、SaveCommand
、DeleteCommand
和 Receiver
。
Command
是一个抽象类,定义了一个execute()
方法,但并不实现该方法。这意味着任何继承Command
的具体类都需要实现自己的execute()
方法。SaveCommand
和DeleteCommand
是继承自Command
的具体命令类。它们都实现了自己的execute()
方法,分别调用Receiver
对象的save()
和delete()
方法。Receiver
类定义了两个方法:save()
和delete()
,分别代表数据的保存和删除操作。Invoker
类负责处理命令。它有一个command
属性,可以设置具体的命令对象,并有一个executeCommand()
方法来执行命令。
示例的使用部分演示了如何使用这些类。首先,创建一个 Receiver
对象,然后创建两个命令对象 saveCommand
和 deleteCommand
,它们都接受同一个 Receiver
对象作为参数。接着,创建一个 Invoker
对象,并设置其命令为 saveCommand
和 deleteCommand
。最后,通过调用 executeCommand()
方法来执行命令。
2. 键盘快捷键
在处理键盘快捷键时,命令模式可以帮助我们将具体操作封装成命令对象,并将其与特定的快捷键关联起来。
// 定义命令接口
class Command {execute() {throw new Error('execute() method must be implemented');}
}
// 定义具体命令类
class CopyCommand extends Command {constructor(receiver) {super();this.receiver = receiver;}execute() {this.receiver.copy();}
}
class PasteCommand extends Command {constructor(receiver) {super();this.receiver = receiver;}execute() {this.receiver.paste();}
}
// 定义接收者类
class Receiver {copy() {console.log('Copying text...');// 执行复制操作的逻辑}paste() {console.log('Pasting text...');// 执行粘贴操作的逻辑}
}
// 定义调用者类
class Invoker {constructor() {this.commands = {};}setCommand(key, command) {this.commands[key] = command;}executeCommand(key) {if (this.commands[key]) {this.commands[key].execute();}}
}
// 使用示例
const receiver = new Receiver();
const copyCommand = new CopyCommand(receiver);
const pasteCommand = new PasteCommand(receiver);
const invoker = new Invoker();
invoker.setCommand('Ctrl+C', copyCommand);
invoker.setCommand('Ctrl+V', pasteCommand);
invoker.executeCommand('Ctrl+C'); // 输出: "Copying text..."
invoker.executeCommand('Ctrl+V'); // 输出: "Pasting text..."
上述示例中定义了一个抽象的命令类 Command
,其中包含一个 execute()
方法。具体的命令类 CopyCommand
和 PasteCommand
继承自 Command
类,并实现了各自的 execute()
方法。
然后定义了一个接收者类 Receiver
,其中包含 copy()
和 paste()
方法,分别表示复制和粘贴操作的具体逻辑。
接下来定义了一个调用者类 Invoker
,其中包含一个 commands
对象用于存储命令对象,以及 setCommand()
和 executeCommand()
方法。setCommand()
方法用于将命令对象与特定的键值进行关联,executeCommand()
方法用于根据给定的键值执行对应的命令。
最后,通过实例化相关的类并进行调用,演示了命令模式的用法。创建了一个接收者对象 receiver
,以及两个命令对象 copyCommand
和 pasteCommand
。然后创建了一个调用者对象 invoker
,并使用 setCommand()
方法将命令对象与对应的键值进行关联。最后通过调用 executeCommand()
方法执行对应的命令,输出相应的结果。
优点和缺点
优点
- 解耦操作和接收者:命令模式将操作封装成对象,使得发送者和接收者之间解耦,可以独立变化。
- 可扩展性:可以轻松地添加新的具体命令类,而无需修改现有代码。
- 支持撤销和重做:通过记录命令历史,可以实现撤销和重做操作。
缺点
- 可能导致类的数量增加:每个具体命令类都需要实现一个执行方法,可能会导致类的数量增加。
- 命令调用的开销:每个命令都需要创建一个对象,并将其传递给调用者执行,可能会带来一定的性能开销。
总结
命令模式是一种非常有用的设计模式,在前端开发中经常用于管理和执行操作。它通过将操作封装成对象,并将其作为参数传递、存储或记录,实现了优雅地管理和执行操作。通过使用命令模式,我们可以提高代码的可维护性和可扩展性。然而,在应用命令模式时需要权衡其带来的优缺点,并根据具体情况进行选择。
相关文章:
【前端设计模式】之命令模式
引言 命令设计模式是一种行为型设计模式,它允许你将命令封装到一个对象中,从而使你可以参数化不同的请求,以及存储、排队、重播和撤销请求。这种设计模式在处理用户界面操作、远程网络请求或其他需要异步执行的操作时非常有用。在前端开发中…...
用c++写一个高精度计算的乘法运算
这段代码是一个用C编写的程序,它实现了两个大整数的乘法运算。 #include<iostream> #include<cstdio> #include<cstring> using namespace std;int main(){char a1[101]"222",b1[101]"2";int a[101],b[101],c[10001],lena,l…...

UE5 ChaosVehicles载具 实现大漂移 (连载四)
载具设置成前驱模式 前轮摩擦力倍增x5 后轮摩擦力倍增x0.5...

基于Arrow的轻量线程池
基于Arrow的轻量线程池 大家好,我是光城,最近花了几周业余时间,开发出这款轻量线程池,代码也全部开源啦,欢迎大家star。 本线程池的设计与实现会有涉及非常多的知识,这些内容也都会以视频的方式分享在知识星…...

泛微OA E-Office V10 OfficeServer 任意文件上传漏洞复现
声明 本文仅用于技术交流,请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 漏洞简介 泛微e-ofice是一款标准化的协同0A办公软件,泛微 …...
spring-cloud-starter-gateway踩坑
1.bean of type org.springframework.http.codec.ServerCodecConfigurer that could not be found. 需要将项目中用到的spring-boot-starter-web依赖给去掉 去掉以下的 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-bo…...

视频SDK开发,多平台SDK快速接入
随着科技的不断发展,视频已经成为了企业业务中不可或缺的一部分。无论是在线教育、企业培训还是产品展示,视频都发挥着至关重要的作用。为了满足企业对视频应用的需求,美摄视频SDK应运而生,为企业提供了一站式的视频解决方案。 一…...

面试官:如何理解CDN?说说实现原理?
一、是什么 CDN (全称 Content Delivery Network),即内容分发网络 构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降…...
C语言 牛客网习题 10.20 day2
1.求最小公倍数 正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。 1≤a, b≤100000 输入描述: 输入两个正整数A和B。 输出描述: 输出A和B的最小公倍数。 #include <st…...

SpringCloud: sentinel热点参数限制
一、定义controller package cn.edu.tju.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.springframework.web.bind.annotation.PathVariable; import org.springframewo…...

PDF编辑阅读 PDF Expert v3.5.2
PDF Expert是由Readdle开发的一款专业的PDF编辑和阅读工具。它可以帮助用户在Mac、iPad和iPhone等设备上查看、注释、编辑、填写和签署PDF文档。 以下是PDF Expert的特点: PDF编辑:PDF Expert提供了丰富的PDF编辑功能,包括添加、删除、移动…...

新技术:WEB组态能页面嵌套、属性继承吗?
目前市面上的工业组态或数据大屏工具有不少,也有很多0代码、无代码、低代码、零代码、低代码概念。 有没有可以支持图纸嵌套、属性暴露的?或者说页面任意嵌套、属性多继承暴露到上层? 比如页面A有输入框,页面B有对话框ÿ…...
【C++ Primer Plus学习记录】复习题
1.如何声明下述数据? a.actor是由30个char组成的数组。 char actor[30]; b.betsie是由100个short组成的数组。 short betsie[100]; c.chuck是由13个float组成的数组。 flaot chuck[13]; d.dipsea是由64个long double组成的数组。 long double dipsea[64]; …...

【LeetCode】62. 不同路径
1 问题 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径?…...

【lesson13】进程地址空间收尾
文章目录 进程地址空间存在的原因原因一原因二原因三 重新理解什么是挂起? 进程地址空间存在的原因 原因一 凡是非法访问或者映射,OS都会识别到,并终止该进程。 例子: 我们会发现我们定义的字符串常量只有只读权限,…...

Microsoft Edge中使用开源的ChatGPT
一、双击打开浏览器 找到:扩展,打开 二、打开Microsoft Edge加载项 三、Move tab新标签 获取免费ChatGPT 四、启用Move tab。启用ChatGPT。 扩展 管理扩展 启用 五、新建标签页,使用GPT 六、使用举例 提问 GPT回复...

【C语言精髓之指针】结构体指针(->与.两个运算符的区别)
/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 通信与信息专业大二在读 * copyright 2023.10* COPYRIGHT 原创技术笔记:转载需获得博主本人同意,且需标明转载源* language C/C* IDE Base on Mic…...

SpringCloud 微服务全栈体系(一)
第一章 认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢? 一、单体架构 单体架构:将业务的所有功能集中在一个项目中开发ÿ…...

Echarts自定义柱状图
目录 效果图 echarts官网找相似图 将柱状图引入html页面中 自定义柱状图 将不需要的属性删除 编辑 修改图形大小 grid 不显示x轴 编辑 不显示y轴线和相关刻度 编辑 y轴文字的颜色设置为自己想要的颜色 修改第一组柱子相关样式(条状) …...
LuatOS-SOC接口文档(air780E)-- ioqueue - io序列操作
ioqueue.init(hwtimer_id,cmd_cnt,repeat_cnt) 初始化一个io操作队列 参数 传入值类型 解释 int 硬件定时器id,默认用0,根据实际MCU确定,air105为0~5,与pwm共用,同一个通道号不能同时为pwm和ioqueue int 一个完…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...