命令模式详解

举报
Further_Step 发表于 2024/12/12 16:56:27 2024/12/12
【摘要】 喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞! 命令模式(Command Pattern)详解 1. 定义命令模式是一种行为型设计模式,它将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化、对请求排队或记录日志,以及支持可撤销的操作。通俗解释:将操作(请求)抽象成独立的对象,从而分离请求的发送者和接收者,允许轻松添加、修改和管理请求。 2. 组成部分组...

喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞

命令模式(Command Pattern)详解

1. 定义

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

通俗解释:
将操作(请求)抽象成独立的对象,从而分离请求的发送者和接收者,允许轻松添加、修改和管理请求。


2. 组成部分

组件 描述
Command(命令接口) 定义命令执行的接口或抽象类,封装命令的行为。
ConcreteCommand 具体命令类,绑定一个接收者并实现具体的操作。
Receiver(接收者) 执行命令的实际逻辑对象。
Invoker(调用者) 调用命令对象的接口,发送请求。
Client(客户端) 创建具体命令对象并将其关联到调用者和接收者。

3. 使用场景

使用场景 描述
需要参数化方法调用 命令模式将行为抽象为对象,方便动态指定行为。
需要支持撤销或恢复操作 通过存储命令对象的状态,实现撤销和恢复功能。
需要记录操作日志 将命令的执行过程记录,方便后续分析或回滚。
需要解耦发送者与接收者 客户端只需操作命令对象,无需关心具体的操作逻辑。

4. 优点与缺点

优点 缺点
解耦性高:将请求发送者与接收者分离。 增加系统复杂度:每个操作都需要创建命令类。
扩展性强:可以方便地新增命令。 命令对象可能过多:复杂系统中命令类数量可能增加。
支持撤销和恢复:便于实现操作历史管理。 性能开销:需要额外的内存存储命令对象。

5. 使用案例

示例描述:

一个智能家居系统,包括电灯和电视,可以通过遥控器控制它们的开关,并支持撤销功能。


C++ 示例

#include <iostream>
#include <stack>
using namespace std;

// 接收者:灯
class Light {
public:
    void on() {
        cout << "Light is ON" << endl;
    }
    void off() {
        cout << "Light is OFF" << endl;
    }
};

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

// 具体命令:打开灯
class LightOnCommand : public Command {
private:
    Light* light;
public:
    LightOnCommand(Light* l) : light(l) {}
    void execute() override {
        light->on();
    }
    void undo() override {
        light->off();
    }
};

// 具体命令:关闭灯
class LightOffCommand : public Command {
private:
    Light* light;
public:
    LightOffCommand(Light* l) : light(l) {}
    void execute() override {
        light->off();
    }
    void undo() override {
        light->on();
    }
};

// 调用者:遥控器
class RemoteControl {
private:
    Command* command;
    stack<Command*> history;
public:
    void setCommand(Command* cmd) {
        command = cmd;
    }
    void pressButton() {
        if (command) {
            command->execute();
            history.push(command);
        }
    }
    void pressUndo() {
        if (!history.empty()) {
            Command* cmd = history.top();
            cmd->undo();
            history.pop();
        }
    }
};

// 客户端代码
int main() {
    Light light;
    LightOnCommand lightOn(&light);
    LightOffCommand lightOff(&light);

    RemoteControl remote;
    remote.setCommand(&lightOn);
    remote.pressButton(); // 打开灯
    remote.pressUndo();   // 撤销打开灯

    remote.setCommand(&lightOff);
    remote.pressButton(); // 关闭灯
    remote.pressUndo();   // 撤销关闭灯

    return 0;
}

C# 示例

using System;
using System.Collections.Generic;

// 接收者:灯
class Light {
    public void On() {
        Console.WriteLine("Light is ON");
    }
    public void Off() {
        Console.WriteLine("Light is OFF");
    }
}

// 命令接口
interface ICommand {
    void Execute();
    void Undo();
}

// 具体命令:打开灯
class LightOnCommand : ICommand {
    private Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void Execute() {
        light.On();
    }
    public void Undo() {
        light.Off();
    }
}

// 具体命令:关闭灯
class LightOffCommand : ICommand {
    private Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void Execute() {
        light.Off();
    }
    public void Undo() {
        light.On();
    }
}

// 调用者:遥控器
class RemoteControl {
    private ICommand command;
    private Stack<ICommand> history = new Stack<ICommand>();

    public void SetCommand(ICommand command) {
        this.command = command;
    }

    public void PressButton() {
        command?.Execute();
        history.Push(command);
    }

    public void PressUndo() {
        if (history.Count > 0) {
            ICommand cmd = history.Pop();
            cmd.Undo();
        }
    }
}

// 客户端代码
class Program {
    static void Main(string[] args) {
        Light light = new Light();
        ICommand lightOn = new LightOnCommand(light);
        ICommand lightOff = new LightOffCommand(light);

        RemoteControl remote = new RemoteControl();
        remote.SetCommand(lightOn);
        remote.PressButton(); // 打开灯
        remote.PressUndo();   // 撤销打开灯

        remote.SetCommand(lightOff);
        remote.PressButton(); // 关闭灯
        remote.PressUndo();   // 撤销关闭灯
    }
}

命令模式的类图

Command+Execute()+Undo()ConcreteCommand+Execute()+Undo()Receiver+Action()Invoker+SetCommand(command: Command)+PressButton()+PressUndo()callsuses

6. 命令模式与其他模式对比

特性 命令模式 策略模式
核心作用 将请求封装为独立对象,支持撤销和记录功能。 定义一系列算法,将其封装并相互替换。
解耦性 解耦发送者和接收者。 解耦算法的使用和实现。
适用场景 需要对操作进行封装或扩展。 需要动态选择算法或行为。

总结

  • 适用场景: 当需要参数化请求、支持撤销操作、记录操作日志时,适合使用命令模式。
  • 优点: 解耦发送者和接收者,支持撤销与恢复操作,扩展性强。
  • 注意事项: 不要因滥用模式而增加系统复杂度,仅在需要时使用。

欢迎关注、点赞、收藏!更多系列内容可以点击专栏目录订阅,感谢支持,再次祝大家祉猷并茂,顺遂无虞
在这里插入图片描述

若将文章用作它处,请一定注明出处,商用请私信联系我!

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。