21.命令模式(Command Pattern)

定义

命令模式(Command Pattern) 是一种行为型设计模式,它将请求封装成一个对象,从而使您可以使用不同的请求、队列、日志请求以及支持撤销操作等功能。命令模式通过将请求(命令)封装成对象,使得客户端可以将请求发送者与请求接收者解耦,从而更灵活地控制操作的执行。

特性

  • 命令对象:将请求封装成一个命令对象,该命令对象包含了执行的具体操作。
  • Invoker(调用者):调用命令对象的 execute() 方法来执行相应的操作。
  • Receiver(接收者):实际执行命令的对象。
  • Client(客户端):客户端创建命令对象并设置命令的接收者。
  • Command(命令接口):定义命令接口,声明执行操作的抽象方法。

命令模式使得我们能够通过不同的命令对象来执行不同的操作,且操作的执行由调用者控制。

场景

适用场景

  • 请求调用者与请求接收者解耦:当客户端希望通过发送请求来调用不同的操作,而不希望知道具体如何执行时,可以使用命令模式。
  • 需要参数化对象:当需要参数化对象进行命令的请求时,命令模式可以封装请求的参数。
  • 支持撤销和恢复操作:命令模式非常适合实现撤销和恢复操作,通过存储命令对象及其执行过程,能够轻松地实现撤销功能。
  • 支持队列或日志请求:命令模式可以将请求封装成对象,方便将多个命令排入队列或记录日志。

应用场景

  • 图形用户界面(GUI)中的按钮点击事件:通过命令模式将按钮的点击事件封装为命令,使得不同按钮的操作可以被独立控制。
  • 事务管理系统:在事务管理中,命令可以表示一系列操作,通过命令模式进行回滚或恢复。
  • 多操作处理系统:在系统中可能有多个操作(如编辑操作),使用命令模式可以统一管理操作。

类设计

命令模式通常包括以下几个角色:

  1. Command(命令接口):声明执行操作的抽象方法。
  2. ConcreteCommand(具体命令类):实现了 Command 接口,封装了具体的请求与接收者之间的关系。
  3. Receiver(接收者):负责执行与请求相关的操作。
  4. Invoker(调用者):调用命令对象来执行请求。
  5. Client(客户端):客户端创建命令对象并设置接收者。

代码实现

我们设计一个 遥控器操作 的例子。遥控器上有多个按钮,每个按钮对应一个操作(如打开电视、关闭空调等)。我们使用命令模式来封装每个按钮的操作,并通过遥控器(调用者)来执行这些操作。

1. 定义命令接口(Command)

#include <iostream>
#include <string>
using namespace std;// 命令接口
class Command {
public:virtual void execute() = 0;  // 执行命令的接口virtual ~Command() {}
};
  • Command 是命令接口,声明了 execute() 方法,该方法将由具体命令类来实现。

2. 定义具体命令类(ConcreteCommand)

// 电视打开命令
class TVOnCommand : public Command {
private:class TV* tv;  // 接收者(电视)public:TVOnCommand(class TV* tv) : tv(tv) {}void execute() override {tv->turnOn();  // 执行命令:打开电视}
};// 电视关闭命令
class TVOffCommand : public Command {
private:class TV* tv;public:TVOffCommand(class TV* tv) : tv(tv) {}void execute() override {tv->turnOff();  // 执行命令:关闭电视}
};// 空调开命令
class ACOnCommand : public Command {
private:class AC* ac;public:ACOnCommand(class AC* ac) : ac(ac) {}void execute() override {ac->turnOn();  // 执行命令:打开空调}
};// 空调关命令
class ACOffCommand : public Command {
private:class AC* ac;public:ACOffCommand(class AC* ac) : ac(ac) {}void execute() override {ac->turnOff();  // 执行命令:关闭空调}
};
  • 每个命令类(如 TVOnCommand、TVOffCommand 等)都实现了 Command 接口,并封装了具体的操作逻辑。
  • 每个命令类持有一个接收者(例如 TV 或 AC),并在 execute() 方法中调用接收者的方法执行具体的操作。

3. 定义接收者类(Receiver)

class TV {
public:void turnOn() {cout << "TV is turned ON." << endl;}void turnOff() {cout << "TV is turned OFF." << endl;}
};class AC {
public:void turnOn() {cout << "AC is turned ON." << endl;}void turnOff() {cout << "AC is turned OFF." << endl;}
};
  • TV 和 AC 类是接收者,包含了执行具体操作的方法(例如打开电视、关闭空调)。

4. 定义调用者类(Invoker)

class RemoteControl {
private:Command* command;  // 持有命令对象public:void setCommand(Command* command) {this->command = command;  // 设置命令对象}void pressButton() {command->execute();  // 执行命令}
};
  • RemoteControl 类是调用者,持有一个命令对象并在按下按钮时执行该命令。

5. 客户端调用

int main() {// 创建接收者对象TV* tv = new TV();AC* ac = new AC();// 创建命令对象Command* tvOn = new TVOnCommand(tv);Command* tvOff = new TVOffCommand(tv);Command* acOn = new ACOnCommand(ac);Command* acOff = new ACOffCommand(ac);// 创建遥控器RemoteControl* remote = new RemoteControl();// 按下按钮打开电视remote->setCommand(tvOn);remote->pressButton();// 按下按钮关闭电视remote->setCommand(tvOff);remote->pressButton();// 按下按钮打开空调remote->setCommand(acOn);remote->pressButton();// 按下按钮关闭空调remote->setCommand(acOff);remote->pressButton();// 清理内存delete tv;delete ac;delete tvOn;delete tvOff;delete acOn;delete acOff;delete remote;return 0;
}

6. 输出结果

TV is turned ON.
TV is turned OFF.
AC is turned ON.
AC is turned OFF.
  • 客户端通过 RemoteControl 类来控制设备的开关,每次按下按钮时,遥控器都会调用相应命令对象的 execute() 方法,来完成实际的操作。

命令模式的优缺点

优点

  • 解耦发送者和接收者:命令模式将请求的发送者和接收者解耦,客户端不需要知道谁会处理请求,只需要发送命令对象即可。
  • 支持撤销和恢复:命令模式可以很容易实现撤销和恢复操作,命令对象可以保存执行过程,支持回滚。
  • 命令队列和日志:命令可以存储在队列中或日志中,方便管理和回溯。
  • 可扩展性:新命令的增加不会影响现有代码,只需要新增具体命令类即可。

缺点

  • 类的数量增加:每个命令都会对应一个具体的命令类,可能会增加类的数量。
  • 系统结构复杂:使用命令模式时,系统中需要管理多个命令类、调用者和接收者,可能使系统结构变得复杂。

场景

适用场景:

  • GUI事件处理:例如,按钮点击、菜单选择等GUI事件的处理,可以通过命令模式将每个事件封装为命令对象。
  • 任务调度系统:将任务封装成命令对象,通过队列或调度器执行任务。
  • 撤销/恢复功能:如文本编辑器、绘图软件等,需要提供撤销和重做的功能,命令模式能很方便地实现该功能。
  • 宏命令:多个命令可以组合成一个“宏命令”,一起执行。

应用场景:

  1. 文本编辑器的撤销操作:用户进行文本编辑时,编辑操作可以封装为命令对象,撤销时,可以通过命令对象来恢复到之前的状态。
  2. 图形编辑器中的操作:在图形编辑器中,用户可以执行绘制、删除、移动等操作,每个操作都可以封装为命令对象,便于撤销和重做。
  3. 网络请求处理:网络请求可以封装为命令对象,每个请求可以通过命令对象来执行,便于管理请求的执行顺序和状态。

总结

命令模式通过将请求封装成命令对象,使得请求的发送者与接收者解耦。它可以帮助简化系统中的操作,支持撤销/恢复功能,并使得系统更具扩展性。命令模式适用于事件处理、任务调度、宏命令等场景,可以使系统的操作更加灵活和可管理。

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

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

相关文章

【deepseek实战】绿色好用,不断网

前言 最佳deepseek火热网络&#xff0c;我也开发一款windows的电脑端&#xff0c;接入了deepseek&#xff0c;基本是复刻了网页端&#xff0c;还加入一些特色功能。 助力国内AI&#xff0c;发出自己的热量 说一下开发过程和内容的使用吧。 目录 一、介绍 二、具体工作 1.1、引…

【OS】AUTOSAR架构下的Interrupt详解(上篇)

目录 前言 正文 1.中断概念分析 1.1 中断处理API 1.2 中断级别 1.3 中断向量表 1.4 二类中断的嵌套 1.4.1概述 1.4.2激活 1.5一类中断 1.5.1一类中断的实现 1.5.2一类中断的嵌套 1.5.3在StartOS之前的1类ISR 1.5.4使用1类中断时的注意事项 1.6中断源的初始化 1.…

一条sql 在MySQL中是如何执行的

在 MySQL 中&#xff0c;SQL 查询的执行涉及多个内存区域和处理步骤&#xff0c;以确保查询能够高效地执行和返回结果。以下是 SQL 查询在 MySQL 中执行时通常会经过的内存路径&#xff1a; 1. 客户端内存 - SQL 文本发送 &#xff1a;SQL 查询首先从客户端发送到 MySQL 服务…

llama.cpp GGUF 模型格式

llama.cpp GGUF 模型格式 1. Specification1.1. GGUF Naming Convention (命名规则)1.1.1. Validating Above Naming Convention 1.2. File Structure 2. Standardized key-value pairs2.1. General2.1.1. Required2.1.2. General metadata2.1.3. Source metadata 2.2. LLM2.2.…

Day30-【AI思考】-错题分类进阶体系——12维错误定位模型

文章目录 错题分类进阶体系——12维错误定位模型**一、认知层错误&#xff08;根源性缺陷&#xff09;****二、操作层错误&#xff08;执行过程偏差&#xff09;****三、心理层错误&#xff08;元认知障碍&#xff09;****四、进阶错误&#xff08;专业级陷阱&#xff09;** 错…

Java/Kotlin双语革命性ORM框架Jimmer(一)——介绍与简单使用

概览 Jimmer是一个Java/Kotlin双语框架 包含一个革命性的ORM 以此ORM为基础打造了一套综合性方案解决方案&#xff0c;包括 DTO语言 更全面更强大的缓存机制&#xff0c;以及高度自动化的缓存一致性 更强大客户端文档和代码生成能力&#xff0c;包括Jimmer独创的远程异常 …

openAI官方prompt技巧(一)

1. 使用最新的模型 2. 将指令放在提示词的开头&#xff0c;并使用 ### 或 """ 来分隔指令和上下文&#xff0c;例如 错误示范❌ 将下面的文本总结为一个要点列表&#xff0c;列出最重要的内容。 Summarize the text below as a bullet point list of the most…

通过制作docker镜像的方式在阿里云部署前端后台服务

前端Dockerfile文件的内容&#xff1a; FROM nginx:版本&#xff0c;如果不指定&#xff0c;默认是latest COPY dist/ /usr/share/nginx/html/dist COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 端口 前端sh脚本文件内容&#xff1a; appName项目名 tar -xvf dist.tar …

Github 2025-02-04 Python开源项目日报 Top10

根据Github Trendings的统计,今日(2025-02-04统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目1Python中的算法实现集合 创建周期:2831 天开发语言:Python协议类型:MIT LicenseStar数量:178357 个Fork数量:…

yolov11模型在Android设备上运行【踩坑记录】

0) 参考资料: https://github.com/Tencent/ncnn?tabreadme-ov-file https://github.com/pnnx/pnnx https://github.com/nihui/ncnn-android-yolov5 https://github.com/Tencent/ncnn?tabreadme-ov-file 1) &#xff1a;将xxx.pt模型转化成 xxx.onnx ONNX&#xff08;Ope…

快速上手——.net封装使用DeekSeek-V3 模型

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,用爱发电,去丈量人心,是否能达到人机合一?开工大吉 新的一年就这么水灵灵的开始了,在这里,祝各位读者新春快乐,万事如意! 新年伊…

2025蓝桥杯JAVA编程题练习Day2

1.大衣构造字符串 问题描述 已知对于一个由小写字母构成的字符串&#xff0c;每次操作可以选择一个索引&#xff0c;将该索引处的字符用三个相同的字符副本替换。 现有一长度为 NN 的字符串 UU&#xff0c;请帮助大衣构造一个最小长度的字符串 SS&#xff0c;使得经过任意次…

【WebLogic】Oracle发布WebLogic 14c最新版本-14.1.2.0

根据Oracle官方产品经理的博客&#xff0c;Oracle于2024年12月20日正式对外发布了WebLogic 14c的第二个正式版本&#xff0c;版本号为 14.1.2.0.0 &#xff0c;目前官方已开放客户端下载。该版本除继续支持 Jakarta EE 8 版本外&#xff0c;还增加了对 Java SE 17&#xff08;J…

Spider 数据集上实现nlp2sql训练任务

NLP2SQL&#xff08;自然语言处理到 SQL 查询的转换&#xff09;是一个重要的自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;其目标是将用户的自然语言问题转换为相应的 SQL 查询。这一任务在许多场景下具有广泛的应用&#xff0c;尤其是在与数据库交互的场景中&…

IDEA+DeepSeek让Java开发起飞

1.获取DeepSeek秘钥 登录DeepSeek官网 : https://www.deepseek.com/ 进入API开放平台&#xff0c;第一次需要注册一个账号 进去之后需要创建一个API KEY&#xff0c;然后把APIkey记录保存下来 接着我们获取DeepSeek的API对话接口地址&#xff0c;点击左边的&#xff1a;接口…

k8s常见面试题2

k8s常见面试题2 安全与权限RBAC配置如何保护 Kubernetes 集群的 API Server&#xff1f;如何管理集群中的敏感信息&#xff08;如密码、密钥&#xff09;&#xff1f;如何限制容器的权限&#xff08;如使用 SecurityContext&#xff09;&#xff1f;如何防止容器逃逸&#xff0…

flutter安卓打包签名

flutter安卓打包签名 1.创建签名文件 keytool -genkeypair -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-key-aliaskeytool 是一个用于管理密钥和证书的命令行工具&#xff0c;通常与 Java 开发工具包 (JDK) 一起使用。my-release-…

React - jsx 语法

在 React 中&#xff0c;JSX&#xff08;JavaScript XML&#xff09;是一种语法扩展&#xff0c;它允许开发者在 JavaScript 代码中使用类似 HTML 的语法。JSX 提升了代码的可读性和可维护性&#xff0c;使得编写和构建用户界面更加直观。它被广泛应用于 React 组件的定义。 一…

intra-mart实现简易登录页面笔记

一、前言 最近在学习intra-mart框架&#xff0c;在此总结下笔记。 intra-mart是一个前后端不分离的框架&#xff0c;开发时主要用的就是xml、html、js这几个文件&#xff1b; xml文件当做配置文件&#xff0c;html当做前端页面文件&#xff0c;js当做后端文件&#xff08;js里…

Linux+Docer 容器化部署之 Shell 语法入门篇 【Shell 替代】

&#x1f380;&#x1f380;Shell语法入门篇 系列篇 &#x1f380;&#x1f380; LinuxDocer 容器化部署之 Shell 语法入门篇 【准备阶段】LinuxDocer 容器化部署之 Shell 语法入门篇 【Shell变量】LinuxDocer 容器化部署之 Shell 语法入门篇 【Shell数组与函数】LinuxDocer 容…