目录

  • 前言
  • 问题
  • 解决方案
  • 结构
  • 代码


前言

命令是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。


问题

假如你正在开发一款新的文字编辑器, 当前的任务是创建一个包含多个按钮的工具栏, 并让每个按钮对应编辑器的不同操作。 你创建了一个非常简洁的 按钮 类, 它不仅可用于生成工具栏上的按钮,还可用于生成各种对话框的通用按钮。
在这里插入图片描述
尽管所有按钮看上去都很相似, 但它们可以完成不同的操作(打开、保存、打印和应用等)。你会在哪里放置这些按钮的点击处理代码呢? 最简单的解决方案是在使用按钮的每个地方都创建大量的子类。 这些子类中包含按钮点击后必须执行的代码。
在这里插入图片描述
你很快就意识到这种方式有严重缺陷。 首先, 你创建了大量的子类, 当每次修改基类 按钮 时, 你都有可能需要修改所有子类的代码。 简单来说, GUI 代码以一种拙劣的方式依赖于业务逻辑中的不稳定代码。
在这里插入图片描述
还有一个部分最难办。复制/粘贴文字等操作可能会在多个地方被调用。例如用户可以点击工具栏上小小的“复制”按钮,或者通过上下文菜单复制一些内容, 又或者直接使用键盘上的 Ctrl+C 。

我们的程序最初只有工具栏, 因此可以使用按钮子类来实现各种不同操作。 换句话来说, 复制按钮 CopyButton 子类包含复制文字的代码是可行的。 在实现了上下文菜单、 快捷方式和其他功能后, 你要么需要将操作代码复制进许多个类中,要么需要让菜单依赖于按钮,而后者是更糟糕的选择。

解决方案

优秀的软件设计通常会将关注点进行分离, 而这往往会导致软件的分层。最常见的例子:一层负责用户图像界面;另一层负责业务逻辑。 GUI 层负责在屏幕上渲染美观的图形, 捕获所有输入并显示用户和程序工作的结果。 当需要完成一些重要内容时(比如计算月球轨道或撰写年度报告,GUI 层则会将工作委派给业务逻辑底层。

这在代码中看上去就像这样: 一个 GUI 对象传递一些参数来调用一个业务逻辑对象。 这个过程通常被描述为一个对象发送请求给另一个对象。
在这里插入图片描述
命令模式建议 GUI 对象不直接提交这些请求。 你应该将请求的所有细节(例如调用的对象、 方法名称和参数列表)抽取出来组成命令类,该类中仅包含一个用于触发请求的方法。

命令对象负责连接不同的 GUI 和业务逻辑对象。 此后, GUI对象无需了解业务逻辑对象是否获得了请求, 也无需了解其对请求进行处理的方式。 GUI 对象触发命令即可, 命令对象会自行处理所有细节工作。
在这里插入图片描述
下一步是让所有命令实现相同的接口。 该接口通常只有一个没有任何参数的执行方法, 让你能在不和具体命令类耦合的情况下使用同一请求发送者执行不同命令。 此外还有额外的好处, 现在你能在运行时切换连接至发送者的命令对象, 以此改变发送者的行为。

你可能会注意到遗漏的一块拼图——请求的参数。 GUI 对象可以给业务层对象提供一些参数。 但执行命令方法没有任何参数,所以我们如何将请求的详情发送给接收者呢?答案是:使用数据对命令进行预先配置,或者让其能够自行获取数据。
在这里插入图片描述
让我们回到文本编辑器。 应用命令模式后, 我们不再需要任何按钮子类来实现点击行为。 我们只需在 按钮 Button 基类中添加一个成员变量来存储对于命令对象的引用, 并在点击后执行该命令即可。

你需要为每个可能的操作实现一系列命令类, 并且根据按钮所需行为将命令和按钮连接起来。

其他菜单、 快捷方式或整个对话框等 GUI 元素都可以通过相同方式来实现。当用户与 GUI 元素交互时,与其连接的命令将会被执行。 现在你很可能已经猜到了, 与相同操作相关的元素将会被连接到相同的命令,从而避免了重复代码。

最后,命令成为了减少 GUI 和业务逻辑层之间耦合的中间层。而这仅仅是命令模式所提供的一小部分好处!

结构

在这里插入图片描述

代码

#include <iostream>
#include <string>
#include <list>
#include <memory>
using namespace std;class Receiver{
public:void operation1(const string& params){cout<<"开始用"<<params<<"执行操作1"<<endl;}void operation2(const string& params){cout<<"开始用"<<params<<"执行操作2"<<endl;}
};class Command{
public:virtual void execute()=0;
};
class ConcreteCommand1:public Command{
public:ConcreteCommand1(shared_ptr<Receiver> receiver, const string& parameter):m_receiver(receiver),m_params(parameter){}void execute() override{m_receiver->operation1(m_params);}
private:shared_ptr<Receiver> m_receiver;string m_params;
};
class ConcreteCommand2:public Command{
public:ConcreteCommand2(shared_ptr<Receiver> receiver, const string& parameter):m_receiver(receiver),m_params(parameter){}void execute() override{m_receiver->operation2(m_params);}
private:shared_ptr<Receiver> m_receiver;string m_params;
};class Invoker{
public:void setCommand(shared_ptr<Command> command){m_commmandList.push_back(command);}void executeCommand(){for(auto& command:m_commmandList){command->execute();}}
private:list<shared_ptr<Command>> m_commmandList;
};int main(){auto receiver=make_shared<Receiver>();auto command1=make_shared<ConcreteCommand1>(receiver,"按钮1");auto command2=make_shared<ConcreteCommand2>(receiver,"按钮2");auto invoker=make_shared<Invoker>();invoker->setCommand(command1);invoker->executeCommand();cout<<"------------------"<<endl;invoker->setCommand(command2);invoker->executeCommand();cout<<"------------------"<<endl;return 0;
}

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

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

相关文章

4-verilog简单状态机

verilog简单状态机 1. always (posedge clk or negedge rst_n) beginif (!rst_n)cnt_1ms < 20b0;else if (cnt_1ms_en)cnt_1ms < cnt_1ms 1b1;elsecnt_1ms < 20d0; endalways (posedge clk or negedge rst_n) beginif(!rst_n)cur_state < s1_power_init;else i…

ICCV2025 | 对抗样本智能安全方向论文汇总 | 持续更新中~

汇总结果来源&#xff1a;ICCV 2025 Accepted Papers 若文中出现的 论文链接 和 GitHub链接 点不开&#xff0c;则说明还未公布&#xff0c;在公布后笔者会及时添加. 若笔者未及时添加&#xff0c;欢迎读者告知. 文章根据题目关键词搜索&#xff0c;可能会有遗漏. 若笔者出现…

SPI通信中CS片选的两种实现方案:硬件片选与软件片选

一. 简介本文简单熟悉一下SPI通信中的片选信号&#xff08;CS&#xff09;的两种实现方案&#xff1a;硬件片选和软件片选&#xff0c;以及两种方案的区别&#xff0c;如何选择。在SPI&#xff08;Serial Peripheral Interface&#xff09;通信中&#xff0c;片选信号&#xff…

IBM 报告称除美国外,全球数据泄露成本下降

IBM 发布的一份针对 113,620 起数据泄露事件的年度全球分析报告发现&#xff0c;平均数据泄露成本同比下降了 9%&#xff0c;这主要归功于更快的发现和遏制速度。 该报告与波耐蒙研究所 (Ponemon Institute) 合作完成&#xff0c;发现全球平均数据泄露成本从 2024 年的 488 万美…

Docker Compose 部署 Dify + Ollama 全栈指南:从裸奔到安全可观测的 AI 应用实战

&#x1f4cc; 摘要 本文以中国开发者视角出发&#xff0c;手把手教你用 Docker Compose 在本地或轻量云主机上部署 Dify Ollama 组合栈&#xff0c;实现“安全、可观测、可扩展”的私有化 AI 应用平台。全文约 8 000 字&#xff0c;包含&#xff1a; 架构图、流程图、甘特图…

「源力觉醒 创作者计划」_全方面实测文心ERNIE-4.5-VL-28B-A3B开源大模型

「源力觉醒 创作者计划」_全方面实测文心ERNIE-4.5-VL-28B-A3B开源大模型1. 文心大模型4.5-28B概述2. 部署ERNIE-4.5-VL-28B-A3B文心大模型2.1. 创建GPU云主机2.2. ERNIE-4.5-VL-28B-A3B部署2.3. 创建大模型API交互接口3. 文心大模型4.5-28B多方面性能评测3.1. 语言理解方面3.2…

数据库学习------数据库事务的特性

在数据库操作中&#xff0c;事务是保证数据一致性和完整性的核心机制。无论是简单的单表更新&#xff0c;还是复杂的多表关联操作&#xff0c;事务都扮演着至关重要的角色。那么什么是数据库事务&#xff1f;数据库事务是一个不可分割的操作序列&#xff0c;它包含一个或多个数…

18-C语言:第19天笔记

C语言&#xff1a;第19天笔记 内容提要 构造类型 结构体共用体/联合体构造类型 数据类型 基本类型/基础类型/简单类型 整型 短整型&#xff1a;short – 2字节基本整型&#xff1a;int – 4字节长整型&#xff1a;long – 32位系统4字节/ 64位系统8字节长长整型&…

centos下安装anaconda

下载 anaconda 安装包 wget https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh 2. 授权 chmod x Anaconda3-2022.05-Linux-x86_64.sh 3. 安装 ./Anaconda3-2022.05-Linux-x86_64.sh 此时显示Anaconda的信息&#xff0c;并且会出现More&#xff0c;继续…

MySQL(172)如何进行MySQL的全局变量设置?

MySQL的全局变量是影响整个服务器设置和行为的参数。可以在服务器启动时通过配置文件设置这些变量&#xff0c;也可以在服务器运行时通过SQL命令动态调整。以下是关于如何设置和管理MySQL全局变量的详细说明和示例代码。 一、通过配置文件设置全局变量 在MySQL服务器启动时&…

【最后203篇系列】030 强化学习探索

前言 我发现在csdn写完一篇文章越来越难了&#xff0c;有n篇写了一半没往下写。原来我觉得补完203篇&#xff0c;凑到一千篇是个很简单的事&#xff0c;没想到还挺难的。 我回想了一下&#xff0c;过去一年大模型领域继续发生这很剧烈的变化&#xff0c;这是一种新的模式 &…

fastGEO v1.7.0 大更新,支持PCA、差异分析、火山图、热图、差异箱线图、去批次等分析

前言 之前一篇文章【fastGEO V1.6.1 这个版本强的可怕&#xff0c;GEO数据自动下载、探针注释、Shiny App】介绍了fastGEO用于GEO数据下载和探针注释的核心功能。 虽然是付费50获取安装包&#xff08;刚开始是20&#xff09;&#xff0c;但也深受欢迎&#xff0c;说明这个R包…

LLM 典型模型技术特性及项目落地全流程实践

在大语言模型(LLM)技术快速迭代的当下,开发者面临的核心挑战已从 “是否使用” 转变为 “如何正确选型并高效落地”。本文将系统剖析当前主流 LLM 的技术特性,结合实际项目架构,提供从模型选型、接口集成到性能优化的全流程技术方案,并附关键代码实现,为工业级 LLM 应用…

机器学习消融实验:方法论演进、跨领域应用与前沿趋势

一、定义与起源 消融实验&#xff08;Ablation Study&#xff09;是一种系统性移除或修改模型关键组件以评估其对整体性能贡献的实验方法论。其术语源于神经科学和实验心理学&#xff08;20世纪60-70年代&#xff09;&#xff0c;指通过切除动物脑区研究行为变化的实验范式。2…

北京-4年功能测试2年空窗-报培训班学测开-今天来聊聊我的痛苦

最近状态很不对劲&#xff0c;因为我很少花时间好好思考&#xff0c;只是处于执行状态&#xff0c;甚至也不太写笔记了&#xff0c;我原以为这样会更高效&#xff0c;现在想想&#xff0c;开始不愿花时间深思才是断弦的开始吧而且从结课后我有了隐瞒&#xff0c;我不想过多透露…

深度解析 | AI 幻觉的形成和应对路径

写这一篇的缘由一是因为我也在摸索如何降低 AI 幻觉提升 AI 工具使用效率&#xff0c;二是因为前两周在MIT学习时老师讲的一节课&#xff0c;刚好也解释了这个问题&#xff0c;所以一并做个总结&#xff0c;分享给大家。 近几年&#xff0c;大型语言模型&#xff08;LLM&#…

Java把word转HTML格式

Java把word转HTML格式&#xff0c;两种方式方式一&#xff1a;maven引入依赖,pom.xml<dependency><groupId>e-iceblue</groupId><artifactId>spire.office.free</artifactId><version>5.3.1</version> </dependency>然后代码读…

#C语言——学习攻略:探索字符函数和字符串函数(一)--字符分类函数,字符转换函数,strlen,strcpy,strcat函数的使用和模拟实现

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言学习》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"编程的本质是理解问题&#xff0c;然后把它分解成可执行的步骤。" 目录 1. 字符分类函…

(吃饭)质数时间

题目描述如果把一年之中的某个时间写作 a 月 b 日 c 时 d 分 e 秒的形式&#xff0c;当这五个数都为质数时&#xff0c;我们把这样的时间叫做质数时间&#xff0c;现已知起始时刻是 2022 年的 a 月 b 日 c 时 d 分 e 秒&#xff0c;终止时刻是 2022 年的 u 月 v 日 w 时 x 分 y…

【RK3568 RTC 驱动开发详解】

RK3568 RTC 驱动开发详解一、Linux RTC 子系统架构​二、设备树配置​三、驱动四、时间相关命令实时时钟&#xff08;RTC&#xff09;是嵌入式系统中不可或缺的硬件模块&#xff0c;负责在系统断电后继续计时&#xff0c;为设备提供稳定的时间基准。本文将以瑞芯微 RK3568 平台…