• 设计模式-命令模式(Command Pattern)


    承接Qt/C++软件开发项目,高质量交付,灵活沟通,长期维护支持。需求所寻,技术正适,共创完美,欢迎私信联系!

    一、命令模式的说明

            命令模式(Command Pattern)是一种行为设计模式,它允许将请求封装成对象,从而使得可以将请求参数化、队列化、并且可以用不同的请求来参数化客户端(调用者)的对象。这个模式也支持可撤销的操作。

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

            Command(命令): 定义了执行操作的接口,通常包括执行方法(execute())和可能的撤销方法(undo())。

            ConcreteCommand(具体命令): 实现了Command接口,持有执行操作所需的相关信息,包括对接收者对象的引用。

            Invoker(调用者): 请求的发送者,通过命令对象来执行请求。

            Receiver(接收者): 实际执行操作的对象。

    二、命令模式的场景

            命令模式在实际应用中有很多常见的案例,以下是其中一些常用的情况:

            菜单和按钮操作:在图形用户界面(GUI)应用程序中,菜单项和按钮通常可以被抽象为命令对象。当用户点击菜单项或按钮时,相应的命令被执行,这样做的好处是可以将用户操作与具体的执行操作解耦。

            多级撤销(Undo)操作:命令模式支持撤销操作,因此它在需要实现撤销多个步骤的应用程序中很有用。每个命令对象可以保存执行操作的状态,以便在撤销时恢复到先前的状态。

            任务调度器:命令模式可以用于实现任务调度器,其中每个任务可以被封装成一个命令对象,并且可以按照一定的顺序执行。

            日志记录:命令模式可以用于实现日志记录系统,每个命令对象的执行都可以被记录下来,从而实现日志记录功能。

            遥控器和家电控制:像前面示例中的遥控器一样,命令模式常用于实现遥控器和家电的控制系统。每个按钮可以关联一个命令对象,当按下按钮时,执行相应的命令。

            数据库事务处理:在数据库操作中,命令模式可以用于实现事务处理,每个数据库操作可以被封装成一个命令对象,事务的提交或回滚可以看作是对一系列命令对象的执行或撤销。

    三、命令模式的优缺点

    优点:

            解耦调用者和接收者:命令模式通过将请求封装成独立的命令对象,从而解耦了请求的发送者和接收者。这使得系统中的对象不需要知道彼此的细节,降低了对象之间的耦合度,提高了系统的灵活性。

            支持撤销和重做:由于命令对象通常会保存执行所需的状态信息,因此可以很容易地支持撤销和重做操作。这对于实现撤销历史记录、撤销栈等功能非常有用。

            支持命令的排队执行:命令模式可以将请求排队,并按照一定的顺序执行。这对于实现任务调度器等功能很有用。

            容易扩展:通过添加新的命令类和接收者类,可以很容易地扩展命令模式,而不需要修改现有的代码。这样使得系统更加灵活和可扩展。

            中心化控制:命令模式将请求封装成对象,使得可以在系统中集中控制命令的执行。这样可以更好地管理和维护系统的行为。

    缺点:

            类爆炸:如果系统中有大量的命令类和接收者类,可能会导致类的数量急剧增加,从而增加了系统的复杂性。

            可能引入过多的代码:在某些情况下,引入命令模式可能会增加过多的代码量,特别是对于简单的功能而言,直接调用函数可能更加简单和直接。

            增加了系统的复杂性:命令模式增加了系统中的额外的抽象层次,可能会增加系统的理解和维护成本。

            不适用于所有情况:命令模式并不适用于所有的情况,特别是对于简单的功能而言,引入命令模式可能会显得过于复杂。

            可能降低执行效率:由于命令模式需要将请求封装成对象,可能会导致额外的性能开销,特别是在系统需要频繁创建和销毁命令对象的情况下。

    四、命令模式的代码

    1. #include
    2. #include
    3. #include
    4. // Command Interface
    5. class Command {
    6. public:
    7. virtual ~Command() {}
    8. virtual void execute() = 0;
    9. };
    10. // Receiver
    11. class Light {
    12. public:
    13. void turnOn() {
    14. std::cout << "Light is on\n";
    15. }
    16. void turnOff() {
    17. std::cout << "Light is off\n";
    18. }
    19. };
    20. // Concrete Command
    21. class TurnOnCommand : public Command {
    22. public:
    23. TurnOnCommand(std::shared_ptr light) : m_light(light) {}
    24. void execute() override {
    25. m_light->turnOn();
    26. }
    27. private:
    28. std::shared_ptr m_light;
    29. };
    30. class TurnOffCommand : public Command {
    31. public:
    32. TurnOffCommand(std::shared_ptr light) : m_light(light) {}
    33. void execute() override {
    34. m_light->turnOff();
    35. }
    36. private:
    37. std::shared_ptr m_light;
    38. };
    39. // Invoker
    40. class RemoteControl {
    41. public:
    42. void setCommand(std::shared_ptr command) {
    43. m_command = command;
    44. }
    45. void pressButton() {
    46. m_command->execute();
    47. }
    48. private:
    49. std::shared_ptr m_command;
    50. };
    51. int main() {
    52. // Receiver
    53. std::shared_ptr light = std::make_shared();
    54. // Concrete Commands
    55. std::shared_ptr turnOnCommand = std::make_shared(light);
    56. std::shared_ptr turnOffCommand = std::make_shared(light);
    57. // Invoker
    58. RemoteControl remote;
    59. // Set commands
    60. remote.setCommand(turnOnCommand);
    61. remote.pressButton(); // Output: Light is on
    62. remote.setCommand(turnOffCommand);
    63. remote.pressButton(); // Output: Light is off
    64. return 0;
    65. }
  • 相关阅读:
    JavaFx学习问题2--音频、视频播放失败情况
    Unexpected tokens (use ‘;‘ to separate expressions on the same line)
    Mybatis-Plus《学习笔记 22版尚硅谷 》——感谢【尚硅谷】官方文档
    深入理解 Jetpack Compose 内核:SlotTable 系统
    手写diff算法
    PAM从入门到精通(十)
    ChatGPT Prompting开发实战(九)
    Docker 必知必会3----使用自己制作的镜像
    整合第三方技术-- 缓存
    scratch学习相关资料汇总
  • 原文地址:https://blog.csdn.net/evesmith520/article/details/136318228