设计模式之命令模式

发布于:2025-08-31 ⋅ 阅读:(21) ⋅ 点赞:(0)

一、定义

命令模式(Command Pattern)是一种行为型设计模式,其核心思想是将请求(操作)封装为一个独立的对象,使得可以用不同的请求参数化其他对象、队列化请求、记录请求日志,以及支持可撤销的操作。

核心解决的问题
在软件设计中,经常需要将 “发出命令的对象” 和 “执行命令的对象” 解耦。例如:

  • 遥控器(发出命令)不需要知道电视(执行命令)的具体工作原理,只需按下按钮即可;
  • 文本编辑器的 “撤销” 功能,需要记录历史操作并反向执行。

命令模式通过将 “命令” 封装为对象,让这两者彻底分离,同时支持更灵活的扩展。

二、命令模式的核心角色

命令模式包含 5 个关键角色,它们协同工作完成命令的封装与执行:

  1. 命令接口(Command)
    声明一个执行操作的抽象方法(通常是 Execute()),所有具体命令都需实现该接口。
  2. 具体命令(ConcreteCommand)
    实现命令接口,内部持有一个 “接收者” 对象,并重写 Execute() 方法 ——调用接收者的具体操作来完成命令。
  3. 接收者(Receiver)
    实际执行命令的对象,包含具体的业务逻辑(例如 “开灯”“关闭文件” 等操作)。
  4. 调用者(Invoker)
    持有命令对象,负责触发命令的执行(例如按钮、遥控器等)。它不关心命令的具体实现,只需调用命令的 Execute() 方法。
  5. 客户端(Client)
    创建具体命令对象,并将其与接收者关联,然后将命令对象交给调用者。

三、工作流程(以 “遥控器控制灯” 为例)

  1. 客户端创建 “开灯命令”(ConcreteCommand),并将其与 “灯”(Receiver)绑定;
  2. 调用者(遥控器的按钮)持有这个 “开灯命令”;
  3. 当用户按下按钮(调用者触发命令),按钮调用命令的 Execute() 方法;
  4. “开灯命令” 的 Execute() 方法调用 “灯” 的 TurnOn() 方法(接收者实际执行操作)。

四、代码示例

// 1. 命令接口
public interface Command {
    void execute();
}

// 2. 接收者(灯)
public class Light {
    public void turnOn() {
        System.out.println("灯打开了");
    }
    
    public void turnOff() {
        System.out.println("灯关闭了");
    }
}

// 3. 具体命令(关灯命令)
public class TurnOffLightCommand implements Command {
    private Light light; // 持有接收者引用
    
    // 构造方法绑定接收者
    public TurnOffLightCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.turnOff(); // 调用接收者的具体操作
    }
}

// 3. 具体命令(开灯命令)
public class TurnOnLightCommand implements Command {
    private Light light; // 持有接收者引用
    
    // 构造方法绑定接收者
    public TurnOnLightCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.turnOn(); // 调用接收者的具体操作
    }
}

// 4. 调用者(遥控器)
public class RemoteControl {
    private Command command; // 持有命令对象
    
    // 设置命令
    public void setCommand(Command command) {
        this.command = command;
    }
    
    // 触发命令执行(按下按钮)
    public void pressButton() {
        command.execute();
    }
}

// 5. 客户端(测试类)
public class Client {
    public static void main(String[] args) {
        // 创建接收者对象
        Light light = new Light();
        
        // 创建具体命令对象,并绑定接收者
        Command turnOnCommand = new TurnOnLightCommand(light);
        Command turnOffCommand = new TurnOffLightCommand(light);
        
        // 创建调用者(遥控器)
        RemoteControl remote = new RemoteControl();
        
        // 测试开灯命令
        remote.setCommand(turnOnCommand);
        remote.pressButton(); // 输出:灯打开了
        
        // 测试关灯命令
        remote.setCommand(turnOffCommand);
        remote.pressButton(); // 输出:灯关闭了
    }
}

五、命令模式的优点

  1. 解耦:发出命令的调用者与执行命令的接收者完全分离,互不依赖。
  2. 扩展性强:新增命令只需添加新的 ConcreteCommand 类,无需修改现有代码(符合开闭原则)。
  3. 支持复杂操作:可实现命令队列(批量执行)、日志记录(记录所有操作)、撤销 / 重做(通过反向命令)等功能。
    本人水平有限,有错的地方还请批评指正。

典型应用场景

  • GUI 按钮操作(每个按钮对应一个命令);
  • 文本编辑器的撤销(Undo)/ 重做(Redo)功能;
  • 事务处理(批量执行命令,失败时回滚);
  • 任务调度(队列化命令,按顺序执行)。

什么是精神内耗?
简单地说,就是心理戏太多,自己消耗自己。
所谓:
言未出,结局已演千百遍;
身未动,心中已过万重山;
行未果,假想灾难愁不展;
事已闭,过往仍在脑中演。


网站公告

今日签到

点亮在社区的每一天
去签到