2023-7-10-第十五式命令模式

简介: 2023-7-10-第十五式命令模式

😉一、基础概念

命令模式是一种行为设计模式,它将请求封装成一个对象,使得可以将请求的发送者与接收者解耦。在命令模式中,通过创建一个具体的命令对象,将请求的操作和参数进行封装,然后将该命令对象传递给调用者。这样做的好处是,可以将请求参数化、延迟执行或者将请求放入队列中等。

以下是命令模式的几个关键角色:

  • Command(命令): 定义了执行操作的接口。通常包含一个 execute() 方法,用于触发具体的操作。
  • ConcreteCommand(具体命令): 实现了 Command 接口,并且具体实现了要执行的操作。它通常会持有一个接收者对象,负责实际执行相应的业务逻辑。
  • Receiver(接收者): 执行具体操作的对象。命令模式将请求的接收者与请求的发送者解耦,通过将具体操作委托给接收者来完成任务。
  • Invoker(调用者): 负责调用命令对象执行请求。它并不知道具体的命令细节,只需调用命令的 execute() 方法即可。
  • Client(客户端): 创建具体的命令对象,并设置其接收者。客户端可以决定命令的执行顺序,可以根据需要进行命令的组合和调用。

使用命令模式可以灵活地控制和扩展请求的操作,也可以实现撤销和恢复功能。此外,命令模式还有助于解耦系统各个对象之间的关系,使得代码更加清晰、可维护和可扩展。


🐱‍🐉二、命令模式实现

以下是一个简单的C++代码示例,演示了如何使用命令模式来实现一个简单的遥控器控制电灯的开关操作。

#include <iostream>
#include <string>
// 命令接口
class Command {
public:
    virtual ~Command() {}
    virtual void execute() = 0;
};
// 具体命令1:开灯命令
class LightOnCommand : public Command {
private:
    Light& light;
public:
    LightOnCommand(Light& light) : light(light) {}
    void execute() override {
        light.on();
    }
};
// 具体命令2:关灯命令
class LightOffCommand : public Command {
private:
    Light& light;
public:
    LightOffCommand(Light& light) : light(light) {}
    void execute() override {
        light.off();
    }
};
// 接收者:电灯类
class Light {
public:
    void on() {
        std::cout << "Light is on." << std::endl;
    }
    void off() {
        std::cout << "Light is off." << std::endl;
    }
};
// 调用者:遥控器类
class RemoteControl {
private:
    Command* onCommand;
    Command* offCommand;
public:
    RemoteControl(Command* onCommand, Command* offCommand)
        : onCommand(onCommand), offCommand(offCommand) {}
    void pressOnButton() {
        onCommand->execute();
    }
    void pressOffButton() {
        offCommand->execute();
    }
};
int main() {
    // 创建接收者对象
    Light light;
    // 创建具体命令对象
    Command* lightOnCommand = new LightOnCommand(light);
    Command* lightOffCommand = new LightOffCommand(light);
    // 创建调用者对象,并设置命令
    RemoteControl remoteControl(lightOnCommand, lightOffCommand);
    // 测试开关操作
    remoteControl.pressOnButton();  // 开灯
    remoteControl.pressOffButton(); // 关灯
    // 释放资源
    delete lightOnCommand;
    delete lightOffCommand;
    return 0;
}

此示例中,使用了命令模式将电灯的开关操作封装成具体命令对象 LightOnCommand 和 LightOffCommand。遥控器类 RemoteControl 充当调用者角色,通过调用具体命令对象的 execute() 方法来执行对应的操作。接收者角色由电灯类 Light 担任,负责实际执行开灯和关灯的动作。

编译和运行代码后,你可以看到输出结果如下:

Light is on.
Light is off.

这表明命令模式成功地将开关操作与电灯对象解耦,可以通过遥控器对象来统一控制电灯的开关。


🎉三、模块之间的关系

在命令模式中,主要涉及以下几个关键角色之间的关系:

  1. 调用者(Invoker): 调用者是一个对象,它要求执行一个具体的命令。调用者并不知道命令的具体实现细节,只需知道如何调用命令的 execute() 方法来触发相应的操作。调用者将请求发送给命令对象,从而解耦了命令的发送者和接收者。
  2. 抽象命令(Command): 抽象命令是一个接口或抽象类,定义了命令的执行方法 execute()。它通常会声明一些可以用于存储命令执行所需参数的方法。抽象命令充当了命令对象的基类,为具体命令提供了统一的接口。
  3. 具体命令(Concrete Command): 具体命令是抽象命令的子类,实现了抽象命令中定义的方法。具体命令持有接收者对象,并将请求转发给接收者来执行具体操作。具体命令负责封装命令的参数和上下文信息,并通过调用接收者的方法来完成实际的业务逻辑。
  4. 接收者(Receiver): 接收者是执行实际业务逻辑的对象。它包含了具体的操作方法,负责执行命令所需的具体操作。接收者知道如何实施和执行一个请求。
  5. 客户端(Client): 客户端创建命令对象,并设置其接收者。客户端可以自由组合不同的命令和接收者,构建出适合需求的命令链。客户端还可以通过调用调用者的方法来触发命令的执行。

总体而言,命令模式中的关系可以概括为:客户端创建具体命令对象,并将其与接收者进行关联;调用者持有具体命令对象,通过调用命令的 execute() 方法来触发命令的执行;命令对象通过调用接收者的方法来完成实际的业务逻辑。这种方式将命令发送者与接收者解耦,提供了一种灵活且可扩展的设计方案。


🐱‍🚀四、注意事项

在使用命令模式时,需要注意以下几点:

  1. 合理划分命令: 在设计命令对象时,要根据实际需求合理划分命令。每个具体命令应该只包含一个操作,尽量保持命令的单一职责原则。
  2. 灵活配置命令链: 命令模式可以通过链式组合多个命令对象来实现复杂的操作。在客户端中,要灵活配置和组合命令对象,以满足具体需求。
  3. 支持撤销和恢复: 命令模式可以很容易地支持撤销和恢复操作。在设计命令对象时,可以提供 undo() 和 redo() 等方法,使得命令可以反向执行以及重新执行。
  4. 命令的动态性: 命令模式支持动态地添加、替换和删除命令。可以按需求动态地创建具体命令对象,并将其注入到调用者中。
  5. 安全性考虑: 在使用命令模式时,要确保对命令的合法性进行验证。例如,检查参数是否有效,避免潜在的安全漏洞。
  6. 考虑性能问题: 如果系统中有大量的命令对象,可能会导致内存占用和性能问题。在设计和实现命令模式时,要注意对资源的合理管理,避免过度消耗内存或造成性能瓶颈。
  7. 与其他模式结合使用: 命令模式可以与其他设计模式结合使用,例如组合模式、工厂模式等。根据实际需求,选择合适的模式组合,以实现更复杂的系统功能。

综上所述,合理划分命令、灵活配置命令链、支持撤销和恢复、考虑安全性和性能问题,以及与其他模式结合使用,都是在使用命令模式时需要注意的事项。这些注意事项将有助于提高系统的可维护性、可扩展性和性能效率。


🎂五、使用场景

命令模式适用于以下场景:

  1. 需要将请求发送者和接收者解耦: 命令模式可以使请求的发送者与接收者之间解耦,让发送者不需要知道具体的接收者是谁以及如何执行操作。这样可以提高系统的灵活性和可扩展性。
  2. 需要支持撤销和恢复操作: 命令模式可以很容易地支持操作的撤销和恢复。通过保存命令对象的历史记录,可以实现撤销操作,并且可以重复执行已撤销的命令来实现恢复操作。
  3. 需要对操作进行参数化或延迟执行: 命令模式允许将操作进行参数化,即将操作及其参数封装在命令对象中,可以根据需要动态改变命令的参数。此外,命令模式还可以在需要时延迟执行命令。
  4. 需要支持事务操作: 命令模式可以将多个操作封装为一个命令对象,从而支持事务操作。在执行命令的过程中,可以保证一系列操作的原子性,要么全部成功执行,要么全部回滚。
  5. 需要实现日志和审计功能: 通过命令模式,可以在命令的执行前后记录日志信息、进行审计等操作。这样可以方便地跟踪命令的执行情况和进行错误调试。
  6. 需要实现命令的队列和调度: 命令模式可以将命令对象放入队列中,并按照一定的顺序逐个执行。这样可以实现命令的调度和异步执行,提高系统的响应性能。

总之,命令模式适用于需要解耦请求发送者和接收者、支持撤销和恢复操作、参数化和延迟执行操作、事务处理、日志记录和审计等功能的场景。它可以提供更加灵活和可扩展的设计方式,有助于降低系统的耦合度,并支持更好的代码组织和维护。


🍳参考文献

🧊文章总结

提示:这里对文章进行总结:

   本文讲了关于命令模式的知识。


目录
相关文章
|
1月前
|
弹性计算 人工智能 关系型数据库
阿里云服务器ESSD AutoPL、ESSD、ESSD Entry 有什么区别?该怎么选系统盘?
阿里云ESSD系列云盘中,ESSD Entry(入门级,6K IOPS/150MB/s)适合开发测试与轻量应用;ESSD云盘(PL0–PL3,最高100万IOPS/4GB/s)性能分级明确,适配各类数据库;ESSD AutoPL则支持容量与性能解耦、预配置及突发性能,弹性更强,适用于AI、大促等波动场景。阿里云服务器ECS官网:https://t.aliyun.com/U/AZBUsA
|
2月前
|
数据采集 存储 前端开发
某乎爬虫进阶:爬取问题+回答+用户信息,构建知识图谱数据源
本文详解如何爬取知乎问题、回答及用户信息构建知识图谱:突破SSR渲染与反爬限制,采用API直调+Cookie认证+UA池+隧道代理方案;设计三表实体模型(问题/回答/用户),支持关系抽取与Neo4j存储,兼顾合规性与实用性。(239字)
265 2
|
8月前
|
人工智能 自然语言处理 搜索推荐
金融智能客服的“模力时刻”:大模型驱动下的技术跃迁
如何手搓一个“有活人感”的金融智能客服?
744 2
|
2月前
|
人工智能 自然语言处理 搜索推荐
多源交叉验证体系在本地生活 GEO 优化中的技术落地与实践
摘要 随着生成式大模型在本地生活服务领域的深度应用,用户消费决策入口逐步向 AI 问答迁移,生成式引擎优化(GEO)成为实体商家数字化运营的新方向。当前行业普遍存在信源单一、实体识别歧义、地域权重失真等问题,导致优化效果不稳定、合规风险高。本文提出一套基于多源交叉验证的 GEO 技术体系,从政商实体、地理空间、内容语义、行为反馈四大维度构建置信度评分模型,并结合贵阳本地市场完成落地实践。数据表明,该体系可将商家实体置信度平均提升 42%,AI 推荐触发率提升 37%,同时全程符合白帽合规要求,为本地生活类 GEO 优化提供了可复用的技术框架。 关键词:生成式引擎优化;多源交叉验证;本地生活服务
291 0
|
4月前
|
人工智能 Java 开发者
Java做AI不行?2026年最大的认知误区
2026年,Java做AI已成现实:Spring官方集成DeepSeek,JBoltAI等框架支持MCP协议与Agent工程化落地。Java凭借稳定性、类型安全与现有系统优势,正成为企业级AI应用的首选底座——不换语言,即可构建可运行的AI服务。
507 1
|
6月前
|
存储 缓存 NoSQL
Redis主从复制
Redis主从复制通过全量同步、命令传播与增量复制三大机制,保障高可用与数据一致性。主节点处理读写并同步数据,从节点分担读请求;借助repl_backlog_buffer环形缓冲区与偏移量机制,实现断线后高效增量恢复,有效避免单点故障与数据丢失。
331 0
|
9月前
|
自然语言处理 编译器 Python
深入理解Python语法分析(从零开始掌握AST与解析器原理)
教程来源https://www.vpshk.cn/本教程带你深入浅出地学习Python语法分析,了解编译原理入门知识。通过ast模块解析代码结构,掌握抽象语法树(AST)的生成与遍历,轻松理解Python解析器工作原理,适合编程新手快速上手。
|
8月前
|
机器学习/深度学习 人工智能 算法
放弃手搓算法吧!ReEvo:让大模型通过“反思”自动进化出SOTA算法
ReEvo提出“语言梯度”新范式,让大模型通过自我反思进化算法。它使LLM不再盲写代码,而是像专家般分析优劣、总结经验,逐步优化出超越人类设计的启发式算法,在芯片布局、TSP等问题上表现SOTA,实现AI自动“炼”算法的突破。
604 0
|
缓存 Java 程序员
函数式编程的Java编码实践:利用惰性写出高性能且抽象的代码
本文会以惰性加载为例一步步介绍函数式编程中各种概念,所以读者不需要任何函数式编程的基础,只需要对 Java 8 有些许了解即可。
函数式编程的Java编码实践:利用惰性写出高性能且抽象的代码
|
弹性计算 运维 安全
RAM账号权限管理
希望通过本次演讲,让大家更深入了解RAM账号权限管理,以某电商网站项目为例,根据研发、测试、生产环境划分及业务流程,使用阿里云RAM访问控制服务规划实现资源分组、账号用户体系、权限分配、安全加固、定期安全检查等措施的最佳实践。
3172 1
RAM账号权限管理

热门文章

最新文章