• 【C++设计模式之命令模式:行为型】分析及示例


    简介

    命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使不同的请求可以被参数化、队列化或记录化。这种模式允许请求的发送者和接收者进行解耦,同时提供更高的灵活性和可扩展性。

    描述

    命令模式的核心思想是通过命令对象来封装请求。命令对象包含了执行请求的接收者和相应的动作。客户端通过将命令对象传递给调用者来触发请求的执行。

    原理

    命令模式包含以下几个关键角色:

    • Command(命令):定义了命令的接口,声明了执行命令的方法。
    • ConcreteCommand(具体命令):实现了Command接口,持有接收者对象,并实现具体的命令操作。
    • Receiver(接收者):负责执行具体命令的对象。
    • Invoker(调用者):有命令对象,调用命令来执行请求。

    类图

    在这里插入图片描述

    其中,Invoker是调用者角色,要求该命令执行这个请求;
    Command是命令角色,需要执行的所有命令都在这里声明,可以是接口或抽象类;
    Receiver是接收者角色,知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者;
    ConcreteCommand将一个接收者对象绑定与一个动作,调用接收者相应的操作,以实现Execute。

    示例

    假设有一个遥控器类 RemoteControl,可以通过按下不同的按钮来执行不同的操作,比如打开电视、关闭电视、调高音量等。我们可以使用命令模式来实现该遥控器:

    #include 
    
    // Command(命令)
    class Command {
    public:
        virtual void execute() = 0;
    };
    
    // Receiver(接收者)
    class TV {
    public:
        void turnOn() {
            std::cout << "电视已打开" << std::endl;
        }
        
        void turnOff() {
            std::cout << "电视已关闭" << std::endl;
        }
        
        void adjustVolume(int volume) {
            std::cout << "音量已调整为:" << volume << std::endl;
        }
    };
    
    // ConcreteCommand(具体命令)
    class TurnOnCommand : public Command {
    private:
        TV* tv;
    public:
        TurnOnCommand(TV* tv) : tv(tv) {}
        
        void execute() {
            tv->turnOn();
        }
    };
    
    class TurnOffCommand : public Command {
    private:
        TV* tv;
    public:
        TurnOffCommand(TV* tv) : tv(tv) {}
        
        void execute() {
            tv->turnOff();
        }
    };
    
    class AdjustVolumeCommand : public Command {
    private:
        TV* tv;
        int volume;
    public:
        AdjustVolumeCommand(TV* tv, int volume) : tv(tv), volume(volume) {}
        
        void execute() {
            tv->adjustVolume(volume);
        }
    };
    
    // Invoker(调用者)
    class RemoteControl {
    private:
        Command* command;
    public:
        void setCommand(Command* command) {
            this->command = command;
        }
        
        void pressButton() {
            command->execute();
        }
    };
    
    int main() {
        // 创建遥控器和电视对象
        RemoteControl remoteControl;
        TV tv;
        
        // 创建具体命令对象
        Command* turnOnCommand = new TurnOnCommand(&tv);
        Command* turnOffCommand = new TurnOffCommand(&tv);
        Command* adjustVolumeCommand new AdjustVolumeCommand(&tv 10);
        
        // 设置具体命令到遥控器
        remoteControl.setCommand(turnOnCommand);
        remoteControl.pressButton(); // 打开电视
        
        remoteControl.setCommand(adjustVolumeCommand);
        remoteControl.pressButton(); // 调高音量
        
        remoteControl.setCommand(turnOffCommand);
        remoteControl.pressButton(); // 关闭电视
        
        // 释放资源
        delete turnOnCommand;
        delete turnOffCommand;
        delete adjustVolumeCommand;
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

    输出结果

    电视已打开
    量已调整为:10
    电视已关闭
    
    • 1
    • 2
    • 3

    解释

    在上面的示例中,遥控器类 RemoteControl 充当调用者角色,持有命令对象并调用命令的 execute() 方法。具体命令类 TurnOnCommand、TurnOffCommand 和 AdjustVolumeCommand 分别对应打开电视、关闭电视和调整音量这三个具体的命令操作。它们实现了 Command 接口,并在执行 execute() 方法时调用接收者 TV 的相应方法。

    结论

    命令模式将请求和执行分离开来,提供了一种松耦合的方式,使得请求发送者和接收者可以方便地扩展和变化。同时,命令模式也可以对请求进行队列化、记录化等操作,增加系统的灵活性和可扩展性。

    应用场景

    • 需要将具体命令与调用者解耦,使得两者间不直接依赖的情况。
    • 需要对请求进行排队、记录操作历史等场景。
    • 需要支持撤销、重做等功能时。

    上述示例实现了一个遥控器控制电视的功能,可以对电视执行打开、关闭和调整音量等操作。通过命令模式,遥控器和具体命令之间实现了解耦,可以很方便地扩展新的命令或修改命令的实现方式。

  • 相关阅读:
    聊聊spring的TransactionalEventListener
    GPT实战系列-如何让LangChain的Agent选择工具
    JS(Dom操作)第十八课
    43、Flink 的 Window Join 详解
    《Head First HTML5 javascript》第7章 表单
    原始递归函数及模拟运行的优化
    java多线程编程:你真的了解线程中断吗?
    shiro基础(一)shiroFilter
    Net6 Xunit 集成测试
    SQL注入之宽字节注入、堆叠注入、二次注入
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/133657777