设计模式之命令模式

文章目录

一、定义

命令模式 (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() 方法(接收者实际执行操作)。

四、代码示例

java 复制代码
// 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)功能;
  • 事务处理(批量执行命令,失败时回滚);
  • 任务调度(队列化命令,按顺序执行)。

什么是精神内耗?

简单地说,就是心理戏太多,自己消耗自己。

所谓:

言未出,结局已演千百遍;

身未动,心中已过万重山;

行未果,假想灾难愁不展;

事已闭,过往仍在脑中演。

相关推荐
Asort8 小时前
JavaScript设计模式(十三)——责任链模式:构建灵活高效的请求处理链
前端·javascript·设计模式
笨手笨脚の8 小时前
设计模式-访问者模式
设计模式·访问者模式·行为型设计模式
bkspiderx8 小时前
C++设计模式之行为型模式:模板方法模式(Template Method)
c++·设计模式·模板方法模式
o0向阳而生0o9 小时前
108、23种设计模式之模板方法模式(17/23)
设计模式·模板方法模式
canonical_entropy11 小时前
组合为什么优于继承:从工程实践到数学本质
后端·数学·设计模式
Deschen1 天前
设计模式-工厂模式
设计模式·简单工厂模式
阿无,1 天前
Java设计模式之工厂模式
java·开发语言·设计模式
Camel卡蒙1 天前
DDD架构——充血模型、领域模型
java·设计模式·架构
rongqing20191 天前
Google 智能体设计模式:目标设定与监控
设计模式
weixin_445476681 天前
一天一个设计模式——开闭原则
服务器·设计模式·开闭原则