设计模式——命令模式

命令模式 (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 小时前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder2 小时前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿星AI工作室9 小时前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
_哆啦A梦1 天前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding
阿闽ooo4 天前
中介者模式打造多人聊天室系统
c++·设计模式·中介者模式
小米4964 天前
js设计模式 --- 工厂模式
设计模式
逆境不可逃4 天前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式
驴儿响叮当20104 天前
设计模式之状态模式
设计模式·状态模式
电子科技圈4 天前
XMOS推动智能音频等媒体处理技术从嵌入式系统转向全新边缘计算
人工智能·mcu·物联网·设计模式·音视频·边缘计算·iot
徐先生 @_@|||5 天前
安装依赖三方exe/msi的软件设计模式
设计模式