设计模式——命令模式

命令模式 (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操作:菜单、按钮操作
  • 宏命令:键盘快捷键
  • 事务处理:数据库事务

使用建议

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

注意事项

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

  • 不要过度使用,增加不必要的复杂度
  • 考虑使用宏命令
相关推荐
小码过河.2 小时前
设计模式——备忘录模式
设计模式·备忘录模式
代码or搬砖2 小时前
设计模式之单例模式
单例模式·设计模式
一条闲鱼_mytube2 小时前
智能体设计模式(四)模型上下文协议-目标设定与监控-异常处理与恢复
microsoft·设计模式
老蒋每日coding3 小时前
AI Agent 设计模式系列(十)——模型上下文协议 (MCP)
人工智能·设计模式
Yu_Lijing3 小时前
基于C++的《Head First设计模式》笔记——迭代器模式
笔记·设计模式
一条闲鱼_mytube16 小时前
智能体设计模式(三)多智能体协作-记忆管理-学习与适应
人工智能·学习·设计模式
小屁猪qAq1 天前
设计模式总纲
开发语言·c++·设计模式
小简GoGo1 天前
前端常用设计模式快速入门
javascript·设计模式
会员果汁1 天前
17.设计模式-单例模式(Singleton)
单例模式·设计模式