设计模式 行为型 命令模式(Command Pattern)与 常见技术框架应用 解析

命令模式(Command Pattern)是一种行为型设计模式,它旨在将请求发送者和接收者解耦,通过将一个请求封装为一个对象,从而允许参数化客户端对象以进行不同的请求、排队请求或记录请求,并支持可撤销操作。

在软件开发中,经常会遇到需要将操作请求和操作的具体实现相分离的场景。比如在一个图形编辑软件里,用户可能执行绘制图形、移动图形、删除图形等多种操作。如果将这些操作的发起和具体执行逻辑紧密耦合在一起,会使代码的可维护性和扩展性变差。命令模式就是为了解决这类问题而诞生的,它把对操作的请求封装成独立的对象,使得我们可以像处理其他数据一样来处理这些操作请求。

一、核心思想

命令模式的核心在于将一个请求(命令)封装为一个对象。这样做的好处是可以将请求参数化,方便对请求进行存储、传递、调用、排队、记录日志以及支持撤销和重做等操作。通过这种方式,把发出命令的责任和执行命令的责任分割开,降低了系统模块之间的耦合度。

二、定义与结构

  1. 定义:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
  2. 结构
    • Command(命令):这是一个抽象类或接口,声明了执行操作的抽象方法execute()。
    • ConcreteCommand(具体命令):实现了Command接口,它知道具体的接收者对象,并在execute方法中调用接收者的相应操作方法。
    • Receiver(接收者):负责执行命令所要求的具体操作,它包含了真正实现业务逻辑的代码。
    • Invoker(调用者):负责调用命令对象执行请求,它持有一个命令对象的引用,通过调用命令对象的execute方法来触发操作。

三、角色

  1. 命令(Command):为所有具体命令类定义了统一的接口,使得调用者可以统一地调用命令的执行方法。
  2. 具体命令(ConcreteCommand):将一个接收者对象和一个动作绑定,在执行execute方法时,调用接收者的相应动作。
  3. 接收者(Receiver):知晓如何执行与请求相关的具体操作,是命令真正的执行者。
  4. 调用者(Invoker):负责安排命令的执行,它并不关心命令的具体实现,只关心如何触发命令的执行。

四、实现步骤及代码示例

  1. 定义命令接口
java 复制代码
public interface Command {
    void execute();
}
  1. 定义接收者类
java 复制代码
public class Light {
    public void on() {
        System.out.println("Light is on");
    }

    public void off() {
        System.out.println("Light is off");
    }
}
  1. 定义具体命令类
java 复制代码
public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}

public class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }
}
  1. 定义调用者类
java 复制代码
public class RemoteControl {
    private Command command;

    public RemoteControl(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}
  1. 测试代码
java 复制代码
public class Main {
    public static void main(String[] args) {
        Light light = new Light();
        Command lightOnCommand = new LightOnCommand(light);
        Command lightOffCommand = new LightOffCommand(light);

        RemoteControl onRemote = new RemoteControl(lightOnCommand);
        RemoteControl offRemote = new RemoteControl(lightOffCommand);

        onRemote.pressButton();
        offRemote.pressButton();
    }
}

五、常见技术框架应用

JavaScript 实现命令模式:

javascript 复制代码
// 接收者
function Door() {
    this.open = function () {
        console.log('Door is opened');
    };
    this.close = function () {
        console.log('Door is closed');
    };
}

// 命令接口
function Command(door) {
    this.door = door;
}

// 具体命令
function OpenDoorCommand(door) {
    Command.call(this, door);
    this.execute = function () {
        this.door.open();
    };
}

function CloseDoorCommand(door) {
    Command.call(this, door);
    this.execute = function () {
        this.door.close();
    };
}

// 调用者
function Remote(door) {
    this.command = null;
    this.setCommand = function (command) {
        this.command = command;
    };
    this.pressButton = function () {
        if (this.command) {
            this.command.execute();
        }
    };
}

// 使用示例
let door = new Door();
let openCommand = new OpenDoorCommand(door);
let closeCommand = new CloseDoorCommand(door);

let remote = new Remote(door);
remote.setCommand(openCommand);
remote.pressButton();

remote.setCommand(closeCommand);
remote.pressButton();

六、应用场景

javascript 复制代码
当你需要在不同的时刻指定、排列和执行请求的时候。
当你需要支持命令的撤销(Undo)功能时。
当你需要将请求作为对象进行传递和操作时。
当你需要组合多个操作形成宏命令时。
  1. 遥控器控制:如上面的示例所示,可以用命令模式实现遥控器来控制不同的家电设备,如电视、音响和灯。
  2. 文本编辑器操作:文本编辑器中的撤销、重做、剪切、复制、粘贴等操作可以使用命令模式来实现。
  3. 菜单系统:图形用户界面(GUI)应用中的菜单项和按钮操作可以通过命令模式来处理。
  4. 游戏中的动作:在游戏中,角色的动作和命令(如攻击、防御、跳跃等)可以使用命令模式来处理。
  5. 多级撤销操作:命令模式支持撤销和重做操作,因此在需要多级撤销的应用中很有用,如图像编辑器或CAD软件。
  6. 日程安排应用:在日程安排应用中,可以使用命令模式来处理添加、编辑、删除事件等操作。

七、优缺点

优点

  1. 解耦调用者和接收者:调用者和接收者之间通过命令对象进行交互,调用者无需了解接收者的具体实现细节,降低了模块之间的耦合度。
  2. 支持命令的扩展和组合:可以很方便地定义新的命令类,也可以将多个命令组合成一个复合命令,以实现更复杂的功能。
  3. 便于实现撤销和重做:通过在命令对象中保存操作的相关状态信息,可以很方便地实现操作的撤销和重做功能。

缺点

  1. 增加系统复杂度:由于引入了命令对象和相关的类,会增加系统的类和对象数量,导致系统复杂度上升,尤其是在命令种类繁多的情况下。
  2. 性能开销:命令的封装和传递会带来一定的性能开销,在对性能要求极高的场景下,需要谨慎评估是否适合使用命令模式。
相关推荐
White-Legend9 分钟前
耗时一天,我用AI开发了AI小程序
人工智能·小程序
Code花园10 分钟前
Bash语言的文件操作
开发语言·后端·golang
机智的奎哥13 分钟前
微信小程序实现长按录音,点击播放等功能,CSS实现语音录制动画效果
前端·javascript·css·微信·微信小程序·小程序
-Bin18 分钟前
client-go中watch机制的一些陷阱
开发语言·后端·golang
EviaHp20 分钟前
递归构建树菜单节点
java·spring boot·后端·maven·idea
半桶水专家20 分钟前
Go语言中变量的作用域详解
开发语言·后端·golang
Jackilina_Stone30 分钟前
【HUAWEI】HCIP-AI-MindSpore Developer V1.0 | 第五章 自然语言处理原理与应用(3 And 4) | 学习笔记
人工智能·笔记·学习·计算机视觉·华为·自然语言处理·huawei
RacheV+TNY26427839 分钟前
未来趋势:电商平台API接口的智能化与自动化发展
网络·人工智能·python·自动化·api
写点什么呢43 分钟前
Pytorch学习12_最大池化的使用
人工智能·pytorch·python·深度学习·学习·pycharm
澄澈i43 分钟前
设计模式学习[15]---适配器模式
c++·学习·设计模式·适配器模式