设计模式——命令模式

命令模式 (Command Pattern)

什么是命令模式?

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

简单来说:命令模式就是将"请求"封装成"对象",可以像操作对象一样操作请求。

生活中的例子

想象一下:

  • 遥控器:遥控器上的按钮对应不同的命令
  • 餐厅点餐:服务员记录订单,厨师按订单做菜
  • 宏命令:键盘快捷键执行一系列操作

为什么需要命令模式?

传统方式的问题

java 复制代码
// 直接调用方法
receiver.action1();
receiver.action2();

问题

  1. 无法撤销:无法撤销操作
  2. 无法记录:无法记录操作历史
  3. 无法排队:无法对请求排队
  4. 耦合度高:调用者与接收者耦合

命令模式的优势

java 复制代码
// 使用命令模式
Command command1 = new ConcreteCommand(receiver);
Command command2 = new ConcreteCommand(receiver);
invoker.setCommand(command1);
invoker.execute();

优势

  1. 解耦合:调用者与接收者解耦
  2. 可撤销:可以撤销操作
  3. 可记录:可以记录操作历史
  4. 可排队:可以对请求排队

命令模式的结构

复制代码
┌─────────────────────┐
│     Command         │  命令接口
├─────────────────────┤
│ + execute(): void   │
│ + undo(): void      │
└──────────┬──────────┘
           │ 实现
           │
┌──────────┴──────────┐
│  ConcreteCommand    │  具体命令
├─────────────────────┤
│ - receiver: Receiver│
│ + execute(): void   │
│ + undo(): void      │
└─────────────────────┘

┌─────────────────────┐
│     Invoker         │  调用者
├─────────────────────┤
│ - command: Command  │
│ + setCommand(): void│
│ + execute(): void   │
└─────────────────────┘

┌─────────────────────┐
│     Receiver        │  接收者
├─────────────────────┤
│ + action(): void    │
└─────────────────────┘

代码示例

1. 定义命令接口

java 复制代码
/**
 * 命令接口
 */
public interface Command {
    /**
     * 执行命令
     */
    void execute();
    
    /**
     * 撤销命令
     */
    void undo();
}

2. 定义具体命令

java 复制代码
/**
 * 具体命令:开灯
 */
public class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.on();
    }
    
    @Override
    public void undo() {
        light.off();
    }
}

/**
 * 具体命令:关灯
 */
public class LightOffCommand implements Command {
    private Light light;
    
    public LightOffCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.off();
    }
    
    @Override
    public void undo() {
        light.on();
    }
}

3. 定义接收者

java 复制代码
/**
 * 接收者:灯
 */
public class Light {
    public void on() {
        System.out.println("灯打开");
    }
    
    public void off() {
        System.out.println("灯关闭");
    }
}

4. 定义调用者

java 复制代码
/**
 * 调用者:遥控器
 */
public class RemoteControl {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void buttonPressed() {
        command.execute();
    }
    
    public void undoButtonPressed() {
        command.undo();
    }
}

5. 使用命令

java 复制代码
/**
 * 命令模式测试类
 * 演示如何使用命令模式实现遥控器功能
 */
public class CommandTest {
    
    public static void main(String[] args) {
        System.out.println("=== 命令模式测试 ===\n");
        
        // 创建接收者
        Light light = new Light();
        
        // 创建命令
        Command lightOn = new LightOnCommand(light);
        Command lightOff = new LightOffCommand(light);
        
        // 创建调用者
        RemoteControl remote = new RemoteControl();
        
        // 测试开灯
        System.out.println("--- 开灯 ---");
        remote.setCommand(lightOn);
        remote.buttonPressed();
        
        // 测试关灯
        System.out.println("\n--- 关灯 ---");
        remote.setCommand(lightOff);
        remote.buttonPressed();
        
        // 测试撤销
        System.out.println("\n--- 撤销 ---");
        remote.undoButtonPressed();
        
        // 连续操作
        System.out.println("\n--- 连续操作 ---");
        remote.setCommand(lightOn);
        remote.buttonPressed();
        remote.buttonPressed();
        remote.setCommand(lightOff);
        remote.buttonPressed();
        
        System.out.println("\n--- 撤销所有操作 ---");
        remote.undoButtonPressed();
        remote.undoButtonPressed();
        remote.undoButtonPressed();
        
        System.out.println("\n=== 命令模式的优势 ===");
        System.out.println("1. 解耦合:调用者与接收者解耦");
        System.out.println("2. 可撤销:可以撤销操作");
        System.out.println("3. 可记录:可以记录操作历史");
        System.out.println("4. 可排队:可以对请求排队");
        System.out.println("5. 易于扩展:新增命令很容易");
        
        System.out.println("\n=== 实际应用场景 ===");
        System.out.println("1. GUI操作:菜单、按钮操作");
        System.out.println("2. 宏命令:键盘快捷键");
        System.out.println("3. 事务处理:数据库事务");
        System.out.println("4. 撤销重做:文本编辑器的撤销重做");
    }
}

命令模式的优点

  1. 解耦合:调用者与接收者解耦
  2. 可撤销:可以撤销操作
  3. 可记录:可以记录操作历史
  4. 可排队:可以对请求排队
  5. 易于扩展:新增命令很容易

命令模式的缺点

  1. 类数量增加:每个命令都需要一个类
  2. 复杂度增加:引入了额外的类

适用场景

  1. 需要撤销:需要撤销操作
  2. 需要记录:需要记录操作历史
  3. 需要排队:需要对请求排队
  4. 菜单操作:菜单、按钮等操作

常见应用场景

  • GUI操作:菜单、按钮操作
  • 宏命令:键盘快捷键
  • 事务处理:数据库事务

使用建议

  • 需要撤销:使用命令模式
  • 需要记录:使用命令模式
  • 简单操作:直接调用即可

注意事项

⚠️ 命令模式虽然强大,但要注意:

  • 不要过度使用,增加不必要的复杂度
  • 考虑使用宏命令
相关推荐
Cosolar11 小时前
DeepSeek Harness 理解 Harness 的设计哲学 - 可组合的插件运行时
人工智能·设计模式·架构
Nebula_g12 小时前
JavaSE基础语法:特殊类(特殊情景下的设计模式)
java·开发语言·设计模式
George_Ye1 天前
同一本书,一人一份:我如何设计 AI 个性化扫书报告
设计模式
莫得感情 o2 天前
设计模式 22 · 三个冷门模式:中介者、访问者、解释器
java·设计模式
AI人工智能+电脑小能手2 天前
大白话说Java设计模式-08-建造者模式(业务实战篇)
java·设计模式·建造者模式·架构设计·对象构建
AustinXu2 天前
从 Claude Code 到 Claude Tag,Harness Engineering 走到了组织这一层
设计模式·团队管理
剧中有戏2 天前
单例模式从入门到精通:一个数据库连接池的完整剖析
设计模式
胡萝卜术2 天前
编译期与运行期的双重防线:从 TypeScript 类型之争到 LLM 输出的自动化择优
前端·设计模式·面试
货拉拉技术2 天前
重塑 Agent 度量衡:基于 LLM-as-a-Judge 的离线评估体系与实践
算法·设计模式
KhalilRuan2 天前
设计模式小记
设计模式