C++设计模式之——命令模式

news2024/11/24 20:27:25

命令模式

  • 概念
  • 创建步骤
  • 示例
    • 示例一
      • 代码实现
      • 运行结果
    • 示例二
      • 代码实现
      • 运行结果
    • 示例三
      • 示例代码
      • 运行结果
    • 示例四
      • 代码实现
      • 运行结果
  • 应用场景

概念

命令模式是一种行为型设计模式,它允许将请求封装为一个对象,从而使得可以参数化客户端请求、将请求排队或者记录请求日志,以及支持可撤销的操作。

在C++中,命令模式通常由一个抽象命令类、具体命令类、命令接收者类和调用者类组成。

创建步骤

命令模式的主要步骤包括:

1.定义抽象命令类(Command):创建一个抽象类或者接口,其中包含一个纯虚的执行方法,用于执行具体的命令操作。
2.创建具体命令类(Concrete Command):继承自抽象命令类,实现具体的命令操作,同时持有一个命令接收者对象。
3.定义命令接收者类(Receiver):这个类包含实际执行命令操作的方法。
4.创建调用者类(Invoker):这个类负责存储和执行命令对象,可以包含一个命令队列,用于存储多个命令对象。

示例

示例一

代码实现

#include <iostream>  
#include <vector>  
#include <string>  

// 命令接口  
class Command {
public:
    virtual void execute() = 0;
};

// 接收者接口  
class Receiver {//子类必须重写抽象类中所有的纯虚函数,否则子类也是抽象类
public:
    virtual void turnOn(std::string light) = 0;
    virtual void setSpeed(int speed) = 0;
};

// 具体接收者  
class LightReceiver : public Receiver {
public:
    void turnOn(std::string light) override {//只重写抽象类中的turnOn函数,LightReceiver也会变为抽象类
        std::cout << "Turning on " << light << std::endl;
    }
    void setSpeed(int speed) override {
        std::cout << "Setting fan speed to " << speed << std::endl;
    }
};

// 具体接收者  
class Fan : public Receiver {
public:
    void turnOn(std::string light) override {
        std::cout << "Turning on " << light << std::endl;
    }
    void setSpeed(int speed) override {
        std::cout << "Setting fan speed to " << speed << std::endl;
    }
};

// 具体命令  
class LightCommand : public Command {
public:
    LightCommand(LightReceiver*pLight,std::string light) : m_pLight(pLight),light_(light) {}
    void execute() override {
        std::cout << "Turning on " << light_ << std::endl;
        m_pLight->turnOn(light_);
    }
private:
    std::string light_;
    LightReceiver* m_pLight;
};

// 具体命令  
class FanCommand : public Command {
public:
    FanCommand(Fan* pFan,int speed) : m_pFan(pFan),speed_(speed) {}
    void execute() override {
        std::cout << "Setting fan speed to " << speed_ << std::endl;
        m_pFan->setSpeed(speed_);
    }
private:
    int speed_;
    Fan* m_pFan;
};

// 调用者接口  
class Invoker {
public:
    virtual void setCommand(Command* command) = 0;
    virtual void execute() = 0;
};

// 具体调用者  
class LightInvoker : public Invoker {
public:
    void setCommand(Command* command) override { m_pCommand = command; }
    void execute() override { m_pCommand->execute(); }
private:
    Command* m_pCommand;
};

int main() {
    LightReceiver light;
    LightCommand lightCommand(&light,"kitchen");
    LightInvoker lightInvoker;
    lightInvoker.setCommand(&lightCommand);
    lightInvoker.execute(); // 执行命令,调用接收者的turnOn方法,输出"Turning on kitchen"  
    return 0;
}

运行结果

在这里插入图片描述

示例二

代码实现

#include <iostream>  
#include <vector>  
#include <string>  

// 命令接口  
class Command {
public:
    virtual void execute() = 0;
};

// 具体命令 - 加法命令  
class AddCommand : public Command {
public:
    AddCommand(int a, int b) : a_(a), b_(b) {}
    void execute() override {
        std::cout << "Result: " << a_ + b_ << std::endl;
    }
private:
    int a_, b_;
};

// 具体命令 - 减法命令  
class SubtractCommand : public Command {
public:
    SubtractCommand(int a, int b) : a_(a), b_(b) {}
    void execute() override {
        std::cout << "Result: " << a_ - b_ << std::endl;
    }
private:
    int a_, b_;
};

// 调用者 - 计算器  
class Calculator {
public:
    void addCommand(Command* command) {
        commands_.push_back(command);
    }
    void executeCommands() {
        for (auto command : commands_) {
            command->execute();
        }
    }
    ~Calculator() 
    {
        for (const auto &command: commands_)
        {
            delete command;
        }
    }
private:
    std::vector<Command*> commands_;
};

int main() {
    Calculator calculator;
    calculator.addCommand(new AddCommand(5, 3)); // 添加加法命令,执行后输出"Result: 8"  
    calculator.addCommand(new SubtractCommand(10, 4)); // 添加减法命令,执行后输出"Result: 6"  
    calculator.executeCommands(); // 执行所有命令,依次输出"Result: 8"和"Result: 6"  
    return 0;
}

运行结果

在这里插入图片描述

示例三

示例代码

#include <iostream>
#include <vector>

// 抽象命令类
class Command {
public:
    virtual void execute() = 0;
};

// 命令接收者类
class Receiver {
public:
    void action() {
        std::cout << "Receiver action" << std::endl;
    }
};

// 具体命令类
class ConcreteCommand : public Command {
private:
    Receiver* receiver;

public:
    ConcreteCommand(Receiver* recv) : receiver(recv) {}

    void execute() {
        receiver->action();
    }
};


// 调用者类
class Invoker {
private:
    std::vector<Command*> commands;

public:
    void addCommand(Command* cmd) {
        commands.push_back(cmd);
    }

    void executeCommands() {
        for (Command* cmd : commands) {
            cmd->execute();
        }
    }
};

int main() {
    Receiver* receiver = new Receiver();
    ConcreteCommand* cmd = new ConcreteCommand(receiver);

    Invoker invoker;
    invoker.addCommand(cmd);
    invoker.executeCommands();

    delete receiver;
    delete cmd;

    return 0;
}

运行结果

在这里插入图片描述

示例四

代码实现

#include <iostream>
#include <vector>

// 命令接口
class Command {
public:
    virtual void execute() = 0;
};

// 具体命令类 - 打开电视
class TurnOnTVCommand : public Command {
public:
    void execute() {
        std::cout << "Turning on the TV" << std::endl;
    }
};

// 具体命令类 - 关闭电视
class TurnOffTVCommand : public Command {
public:
    void execute() {
        std::cout << "Turning off the TV" << std::endl;
    }
};

// 遥控器
class RemoteControl {
private:
    Command* command;

public:
    void setCommand(Command* cmd) {
        command = cmd;
    }

    void pressButton() {
        command->execute();
    }
};

int main() {
    RemoteControl remote;

    TurnOnTVCommand onCommand;
    TurnOffTVCommand offCommand;

    remote.setCommand(&onCommand);
    remote.pressButton();

    remote.setCommand(&offCommand);
    remote.pressButton();

    return 0;
}

运行结果

在这里插入图片描述

应用场景

1.实现宏命令:命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
2.日志记录和事务处理:在命令模式中,可以方便地增加额外功能,比如日志记录。此外,如果一个操作需要由多个子操作构成,而这些子操作需要被打包在一起作为一个单独的事务来执行,命令模式可以帮助实现这一功能。
3.支持撤销和重做:命令模式可以方便地实现撤销(Undo)和重做(Redo)功能。
4.队列请求:当需要将请求排队,例如用户界面中的点击事件或网络请求,命令模式可以将这些请求封装为对象并放入队列中等待处理。
5.多线程操作:命令模式可以帮助多线程操作,多个线程可以发出操作命令,程序可以在后台自动发出指令并处理其他业务,而不用等待线程完成操作。
6.系统需要将请求调用者和请求接收者解耦:命令模式使调用者和接收者不直接交互。
7.系统随机请求命令或经常增加、删除命令:命令模式可以方便地实现这些功能。
8.当系统需要执行一组操作时:命令模式可以定义宏命令来实现该功能。

总的来说,命令模式的应用场景主要在于解耦请求与实现,封装接收方具体命令的实现细节,使得请求方的代码架构稳定,具备良好的扩展性。

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

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

相关文章

【数据结构】八大排序之简单选择排序算法

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.简单选择排序简介及思路 二.简单选择排序的代码实现 三.简单选择排序的优化 四.简单选择排序的时间复杂度分析 结语 一.简单选择排序简介及思路 简单选择排序算法…

k8s集群内部署nexus

一、前言 在k8s集群中部署nexus服务需要使用到pv、pvc服务来存储nexus的数据&#xff0c;需要使用service服务来提供对外访问nexus服务的端口&#xff0c;需要使用deployment服务来管理nexus服务&#xff0c;接下来就是用这些服务来在k8s集群中搭建nexus&#xff0c;pv服务使用…

C#中HttpWebRequest的用法

前言 HttpWebRequest是一个常用的类&#xff0c;用于发送和接收HTTP请求。在C#中使用HttpWebRequest可以实现各种功能&#xff0c;包括发送GET和POST请求、处理Cookie、设置请求头、添加参数等。本文将深入介绍HttpWebRequest的用法&#xff0c;并给出一些常见的示例。 目录 前…

MATLAB 主成分分析PCA拟合平面点云 (42)

MATLAB 主成分分析PCA拟合平面点云 (42) 一、算法介绍二、算法实现一、算法介绍 主成分分析(Principal Component Analysis,PCA)是一种常用的数据降维和特征提取技术。它的主要思想是通过线性变换将数据投影到一个新的坐标系,使得在新的坐标系中数据的方差最大化。在3D点…

vp与vs联合开发-通过CogAcqFifoTool工具连接相机

1.完成相机硬件配置后 2.完成vp与vs联合开发配置功能后 1.创建winform 项目 目的 : 搭建 界面应用 2. 1. vpp文件存入 项目的debug 目录中 目的&#xff1a; 在项目中加载本地vpp文件 读取相机工具 1.控件CogRecordDisplay 用于显示相机拍摄照片和实施显示的窗口 2和3 …

PostgreSQL的安装、配置与使用指南

文章目录 一、介绍二、安装1、下载安装2、验证 三、配置1、远程连接配置1&#xff09;配置postgresql.conf2&#xff09;配置pg_hba.conf3&#xff09;重启 2、配置数据库的日志 四、图形化界面1、pgAdmin2、Navicat 一、介绍 PostgreSQL是一个功能强大的 开源 的关系型数据库…

[学习笔记]批量迁移数据库文件

拷贝数据库文件 首先在本地运行如下SQL语句&#xff0c;查看数据库文件的磁盘位置 SELECT name, physical_name AS CurrentLocation, state_desc FROM sys.master_files默认是保存在C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA目录下 首先复制数据…

随时随地刷题题库小程序源码系统+完整代码包+安装部署教程

互联网的普及和在线教育的发展&#xff0c;越来越多的人开始利用碎片时间进行学习。为了满足这一需求&#xff0c;随时随地刷题题库小程序应运而生。该小程序提供了一个便捷的刷题平台&#xff0c;用户可以在任何时间、任何地点进行刷题练习&#xff0c;提高自己的学习效率。 …

C# Tcplistener,Tcp服务端简易封装

文章目录 前言相关文章前言设计代码简单使用运行结果 前言 我最近有个需求要写Tcp服务端&#xff0c;我发现Tcp服务端的回调函数比较麻烦&#xff0c;简化Tcp的服务&#xff0c;我打算自己封装一个简单的Tcp服务端。 相关文章 C# TCP应用编程三 异步TCP应用编程 C# Tcpclient…

开源一个超好用的接口Mock工具——Msw-Tools

作为一名前端开发&#xff0c;是不是总有这样的体验&#xff1a;基础功能逻辑和页面UI开发很快速&#xff0c;本来可以提前完成&#xff0c;但是接口数据联调很费劲&#xff0c;耗时又耗力&#xff0c;有时为了保证进度还不得不加加班。 为了摆脱这种痛苦&#xff0c;经过一周的…

uniapp 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…

掌握电脑开机密码设置技巧,让你的电脑数据更安全!

在现代社会&#xff0c;电脑已经成为了我们日常生活中必不可少的工具。然而&#xff0c;随着科技的发展&#xff0c;我们使用电脑也面临着一些安全隐患。为了保护个人数据的安全&#xff0c;设置开机密码就变得十分重要。本文将为大家介绍电脑怎么设置开机密码&#xff0c;以保…

在RTOS中验证互斥量有效解决优先级反转现象

我们在stm32f103c8t6单片机上验证RTOS互斥量有效解决优先级反转现象&#xff0c;利用stm32cube进行RTOS的配置。在选择TIM2当做RTOS的时钟&#xff0c;裸机的时钟源默认是 SysTick&#xff0c;但是开启 FreeRTOS 后&#xff0c;FreeRTOS会占用 SysTick &#xff08;用来生成1ms…

数组去重及去除指定值,每一个对象添加属性值

1、数组去重ES6写法 Set() // 数组去重 let arr [1,2,4,6,3,2,6,7,7,2,9,0,1,5] arr [...new Set(arr)] console.log(arr); 2、数组去除指定值 filter() // 数组去除指定值 let arr [1,2,4,6,3,2,6,7,7,2,9,0,1,5] const num 7 arr arr.filter(item>item!num) cons…

Go集成elasticsearch8极简demo,光速入门

Go集成elasticsearch8极简demo,光速入门 配置go环境创件go mod工程代码实现配置go环境 编辑器添加goproxy GO111MODULE=on;GOPROXY=https://mirrors.wps.cn/go/,https://goproxy.cn,direct;GOSUMDB=off创件go mod工程 mkdir demo cd demo go mod init demo代码实现 在demo…

测试用例的修改更新

测试用例的修改更新是指测试过程中由于用户需求的改变&#xff0c;或者测试过程中发现有新的需求产生&#xff0c;使得测试用例需要进行修改。修改更新测试用例不仅是一种测试技术&#xff0c;更是一种质量保证的方法。但修改和更新测试用例的技术要点在于&#xff1a; 1、执行…

设计模式之创建型设计模式(一):单例模式 原型模式

单例模式 Singleton 1、什么是单例模式 在软件设计中&#xff0c;单例模式是一种创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 这意味着无论何时需要该类的实例&#xff0c;都可以获得相同的实例&#xff0c;而不会创建…

API接口能力不足?Bug处理慢?Lazada开放平台API商品接入

7月30日正式发布的Lazada开放平台2.0&#xff08;Lazada Open Platform 2.0&#xff09;&#xff0c;从商品API、订单API、IM&#xff08;即时通信&#xff09; API、营销工具等几大方向&#xff0c;带来全新升级的API体系&#xff0c;共新增47个接口、优化19个接口&#xff0c…

JVM-9-Class类文件的结构

Java技术能够一直保持着非常良好的向后兼容性&#xff0c;Class文件结构的稳定功不可没。 Class文件是一组以8个字节为基础单位的二进制流&#xff0c;各个数据项目严格按照顺序紧凑地排列在文件之中。 Class文件格式采用一种类似于C语言结构体的伪结构来存储数据&#xff0c…

详细教程 - 从零开发 鸿蒙harmonyOS应用 第八节——鸿蒙操作系统中的文件读写操作封装

一、引言 鸿蒙操作系统是华为自主研发的全场景操作系统。在这篇博客中&#xff0c;我们将探讨如何在鸿蒙操作系统中实现文件读写操作的封装。 二、文件读写操作 在鸿蒙操作系统中&#xff0c;文件读写操作是一个常见的需求。下面是一个简单的文件读写操作的封装示例&#xff1…