前端设计模式之旅:命令模式

在这里插入图片描述

引言

在这里插入图片描述

使用命令模式,我们可以将执行特定任务的对象与调用该方法的对象解耦。

核心思想

命令模式的核心思想是将请求封装成一个对象,从而使请求的发起者和请求的执行者解耦。

  • 请求的发起者只需要知道如何创建命令对象并将其传递给请求者,而不需要知道命令对象的具体实现细节。

  • 命令模式还支持可撤销操作,因为命令对象可以保存执行前的状态,并在需要时恢复状态。这样,可以通过撤销命令对象来撤销之前的操作。

适用场景

1. 需要将请求发送者和接收者解耦的场景

命令模式可以将请求封装成对象,从而使得请求的发送者和接收者之间解耦,使得系统更加灵活。

2. 需要支持撤销和重做操作的场景

命令模式可以将请求封装成对象,并提供撤销和重做操作,从而使得系统更加灵活和可靠。

3. 需要支持事务操作的场景

命令模式可以将多个请求封装成一个事务,从而保证事务的原子性和一致性。

4. 需要支持日志和审计功能的场景

命令模式可以将请求封装成对象,并记录请求的执行情况,从而支持日志和审计功能。

5. 需要支持队列请求的场景

命令模式可以将请求封装成对象,并将请求放入队列中,从而支持队列请求的场景。

案例实践

在这里插入图片描述

假设我们有一个简单的计算器,它可以执行加、减、乘、除四种操作。

我们可以使用命令模式来实现这个计算器,将每个操作封装成一个命令对象,然后将命令对象传递给计算器,从而实现不同的操作。

整体步骤

  1. 第一步:我们定义一个命令接口,它包含一个execute方法
  2. 第二步:我们定义四个具体的命令类,分别对应加、减、乘、除四种操作
  3. 第三步:我们定义一个计算器类,它包含一个命令队列和一个执行命令的方法
  4. 第四步:使用这些类来实现一个简单的计算器

第一步,我们定义一个命令接口,它包含一个execute方法:

class Command {
  execute() {}
}

第二步,我们定义四个具体的命令类,分别对应加、减、乘、除四种操作:

加法操作:AddCommand类继承Command

class AddCommand extends Command {
  constructor(receiver, value) {
    super();
    this.receiver = receiver;
    this.value = value;
  }

  execute() {
    this.receiver.add(this.value);
  }
}

减法操作:SubCommand类继承Command

class SubCommand extends Command {
  constructor(receiver, value) {
    super();
    this.receiver = receiver;
    this.value = value;
  }

  execute() {
    this.receiver.sub(this.value);
  }
}

乘法操作:MulCommand类继承Command

class MulCommand extends Command {
  constructor(receiver, value) {
    super();
    this.receiver = receiver;
    this.value = value;
  }

  execute() {
    this.receiver.mul(this.value);
  }
}

除法操作:DivCommand类继承Command

class DivCommand extends Command {
  constructor(receiver, value) {
    super();
    this.receiver = receiver;
    this.value = value;
  }

  execute() {
    this.receiver.div(this.value);
  }
}

其中,每个命令类都包含一个接收者对象和一个操作值,execute方法会调用接收者对象的相应方法来执行操作。

第三步,我们定义一个计算器类,它包含一个命令队列和一个执行命令的方法:

// 计算器类
class Calculator {
  constructor() {
    this.commands = [];
    this.current = 0;
  }
// addCommand方法用于将命令对象添加到命令队列中
  addCommand(command) {
    this.commands.push(command);
  }
// executeCommand方法用于执行当前命令
  executeCommand() {
    this.commands[this.current].execute();
    this.current++;
  }
// undo方法用于撤销上一个命令
  undo() {
    this.commands[this.current - 1].execute();
    this.current--;
  }
// redo方法用于重做上一个命令
  redo() {
    this.commands[this.current].execute();
    this.current++;
  }
}

其中,addCommand方法用于将命令对象添加到命令队列中,executeCommand方法用于执行当前命令,undo方法用于撤销上一个命令,redo方法用于重做上一个命令。

第四步,使用这些类来实现一个简单的计算器:

const calculator = new Calculator();
const receiver = {
  value: 0,
  add: function (value) {
    this.value += value;
    console.log(`Add ${value}, result: ${this.value}`);
  },
  sub: function (value) {
    this.value -= value;
    console.log(`Sub ${value}, result: ${this.value}`);
  },
  mul: function (value) {
    this.value *= value;
    console.log(`Mul ${value}, result: ${this.value}`);
  },
  div: function (value) {
    this.value /= value;
    console.log(`Div ${value}, result: ${this.value}`);
  },
};

const addCommand = new AddCommand(receiver, 10);
const subCommand = new SubCommand(receiver, 5);
const mulCommand = new MulCommand(receiver, 2);
const divCommand = new DivCommand(receiver, 4);

calculator.addCommand(addCommand);
calculator.addCommand(subCommand);
calculator.addCommand(mulCommand);
calculator.addCommand(divCommand);

具体执行及其结果:

calculator.executeCommand(); // Add 10, result: 10
calculator.executeCommand(); // Sub 5, result: 5
calculator.executeCommand(); // Mul 2, result: 10
calculator.executeCommand(); // Div 4, result: 2.5

calculator.undo(); // Div 4, result: 10
calculator.undo(); // Mul 2, result: 20
calculator.undo(); // Sub 5, result: 25
calculator.undo(); // Add 10, result: 35

calculator.redo(); // Add 10, result: 10
calculator.redo(); // Sub 5, result: 5
calculator.redo(); // Mul 2, result: 10
calculator.redo(); // Div 4, result: 2.5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/249592.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python基础入门第四节,第五节课笔记

第四节 第一个条件语句 if 条件: 条件成立执行的代码1 条件成立执行的代码2 ...... else: 条件不成立执行的代码1 条件不成立执行的代码2 …… 代码如下: 身高 float(input("请输入您的身高(米):")) if 身高 >1.3:print(f您的身高是{身高},已经超过1.3米,您需…

python+appium自动化常见操作

1、点击、输入操作 #点击 driver.find_element(id,com.lemon.lemonban:id/navigation_my).click() #输入 driver.find_element(id,com.lemon.lemonban:id/et_password).send_keys(abc)2、隐形等待 driver.implicitly_wait(10)3、显性等待 #显性等待 locator (xpath,xpath) wai…

数学公式推导中 “:=“和“:=“的区别

A:B 将A定义为(记为,令为)B A:B 将B定义为(记为,令为)A

fckeditor编辑器在Chrome浏览器下编辑时多出空格解决方法

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置,前后端开发环境的配置,编辑器的配置,网络服务的配置,网络命令的应用与配置,windows常见问题的解决等。 文章目录 结尾语网络的梦想 dedecms网站后台采用fckedi…

『OPEN3D』1.5.1 动手实现点云暴力最近邻

本专栏地址: https://blog.csdn.net/qq_41366026/category_12186023.html?spm=1001.2014.3001.5482https://blog.csdn.net/qq_41366026/category_12186023.html?spm=1001.2014.3001.5482 1、暴力最近邻法 暴力最近邻法 (Brute-force Nearest Neighbour Search,BF 搜索) 是…

《人工智能导论》知识思维导图梳理【第6章节】

文章目录 第六章 知识图谱1 知识图谱概述2 知识图谱相关概念3 知识图谱的逻辑结构4 知识图谱的数据存储5 知识图谱的构建过程6 例题 markdown内容的分享 第六章 知识图谱 1 知识图谱概述 2 知识图谱相关概念 3 知识图谱的逻辑结构 4 知识图谱的数据存储 5 知识图谱的构建过程 6…

论文阅读——Mask DINO(cvpr2023)

DINO是检测,Mask DINO是检测分割。 几个模型对比: 传统的检测分割中,检测头和分割头是平行的,Mask DINO使用二分图匹配bipartite matching提高匹配结果的准确性。 box对大的类别不计算损失,因为太大了,会…

Gitee:远程仓库步骤

第一步:新建仓库 第二步:初始化本地仓库,git init 创建分支 git branch 新分支名 第三步:git add . :添加到暂存区 第四步:git config –global user.email关联邮箱,user.name用户名 第…

UE5 Landscaping MapBox 学习笔记

1. Landscaping MapBox 操作录屏 https://www.bilibili.com/video/BV113411U7T9/?spm_id_from333.337.search-card.all.click&vd_source707ec8983cc32e6e065d5496a7f79ee6 安装Landscaping与LandscapingMapbox两个插件 打开Landscaping窗口,这里应该要在Proj…

【CDP】CDP 集群通过Knox 访问Yarn Web UI,无法跳转到Flink Web UI 问题解决

一、前言 记录下在CDP 环境中,通过Knox 访问Yarn Web UI,无法跳转到Flink Web UI 的BUG 解决方法。 二、问题复现 登录 Knox Web UI 找到任一 Flink 任务 点击 ApplicationMaster 跳转 Flink WEB UI 出问题 内容空白,无法正常跳转到…

python 小程序学生选课系统源码

开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 学生: 登录,选课(查看课程及选择),我的成绩,…

Unity 使用AddTorque方法给刚体施加力矩详解

给刚体施加力,除了使用AddForce方法,我们还可以使用AddTorque方法。该方法是通过施加力矩给刚体以力。AddTorque方法从形式上跟AddForce差不多,它也有4个重载方法: 1、AddTorque(Vector3 torque);使用Vector3类型参数…

kakfa实战指引-实时海量流式数据处理

前言 我们最终决定从头开始构建一些东西。我们的想法是,与其专注于保存成堆的数据,如关系数据库、键值存储、搜索索引或缓存,不如专注于将数据视为不断发展和不断增长的流,并围绕这个想法构建一个数据系统——实际上是一个数据架…

基于YOLOv8深度学习的高精度车辆行人检测与计数系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…

zync spi flash 频率配置

spi flash的频率配置 代码流程及最终的频率值。 驱动目录 基于4.14.55 内核, \drivers\spi\spi-dw-fmsh.c (控制器) \drivers\spi\spi-dw.c \drivers\mtd\devices\m25p80.c (设备) \drivers\spi\spi.c spi dts配置说明 spi0: spie000100…

3、Kafka 线上集群部署方案怎么做?

文章目录 1、操作系统的选择1.1、I/O 模型的使用1.2、数据网络传输效率1.3、社区支持度 2、磁盘的选择3、磁盘容量的规划3.1、举例思考本问题:3.2、计算一下:3.3、规划磁盘容量时你需要考虑下面这几个元素: 4、带宽规划4.1、计算 总结 1、操作…

提供一个数据库的表,然后,分页显示表中所有信息,一页10个,此表130条信息。最后再以饼图显示男 女 未知 人数的情况。

运行之后显示的效果&#xff1a; 如果是新项目&#xff0c;建立项目后&#xff0c;把mysql驱动放到指定的目录下即&#xff1a; WebContent\WEB-INF-lib 我用的驱动是 mysql-connector-j-8.0.33.jar 展示页 listpage.jsp <%page import"java.util.Map.Entry"%&g…

break用法

break他是用于从循环语句中跳出一层循环体的&#xff0c;提前结束循环 但是值得注意的点事break只能用在循环语句和switch当中 那么我们上代码进行具体的理解&#xff1a; 如果圆的面积大于100就会终止循环&#xff0c;那么如何体现出他只能终结一个循环呢&#xff0c;请看下…

独立站低成本流量:优化用户体验,实现精准营销

在当今的数字化时代&#xff0c;获取流量是每个网站成功的关键。然而&#xff0c;随着竞争的加剧&#xff0c;流量获取的成本也在逐渐上升。对于许多独立站来说&#xff0c;如何低成本的获取流量变得越来越具有挑战性。本文Nox聚星将和大家探讨独立站如何通过网站优化和精准营销…

3. 内容模块管理 - 异常处理与校验

文章目录 内容模块管理一、自定义异常1.1 全局异常处理器1.2 自定义异常1.3 异常统一响应类1.4 封装通用异常信息 二、JSR303校验2.1 Maven坐标2.2 校验规则2.3 代码示例2.4 捕捉校验异常2.5 分组校验2.6 备注 三、全局异常处理23.1 全局异常处理器3.2 结果集3.3 常用注解3.3.1…