15.设计模式-COMMAND(命令)

一、模式定义与核心思想

命令模式是一种行为型设计模式,其核心目标是通过将请求封装为独立对象,实现请求发送者与执行者的解耦,支持请求的参数化、队列化、撤销与重做。该模式通过将操作抽象为可存储、传递的对象,赋予系统以下核心能力:

  1. 解耦请求与执行:客户端无需知道具体执行逻辑(如餐厅点餐时顾客与厨师的解耦)。
  2. 事务管理:支持操作的回滚、重试(如文本编辑器的撤销功能)。
  3. 灵活扩展:动态添加新命令,支持宏命令组合(如智能家居的自动化场景)。
  4. 异步处理:实现请求的延迟执行与队列调度(如任务队列系统)。

经典场景

  • 文本编辑器的撤销/重做堆栈
  • GUI按钮与菜单的事件绑定
  • 智能家居的遥控器指令系统
  • 分布式系统的命令日志与事务补偿

二、模式组成与UML类图

核心角色
  1. Command(命令接口)
    • 声明执行操作的统一接口(如execute()undo())。
  1. ConcreteCommand(具体命令)
    • 实现命令接口,关联接收者对象(如LightOnCommand封装开灯操作)。
  1. Receiver(接收者)
    • 实际执行业务逻辑的对象(如电灯、数据库连接池)。
  1. Invoker(调用者)
    • 触发命令执行(如遥控器按钮、GUI事件处理器)。
  1. Client(客户端)
    • 组装命令对象与接收者的关系1****8
UML类图
classDiagram
    class Command {
        <<interface>>
        +execute()
        +undo()
    }

    class ConcreteCommand {
        -receiver: Receiver
        +execute()
        +undo()
    }

    class Receiver {
        +action()
    }

    class Invoker {
        -command: Command
        +setCommand()
        +executeCommand()
    }

    class Client

    Command <|.. ConcreteCommand
    ConcreteCommand --> Receiver
    Invoker --> Command
    Client --> ConcreteCommand
    Client --> Receiver


三、代码实现示例

场景:实现支持撤销操作的智能家居灯光控制

// 1. 接收者(电灯)
class Light {
    void turnOn() { System.out.println("灯光开启"); }
    void turnOff() { System.out.println("灯光关闭"); }
}

// 2. 命令接口
interface Command {
    void execute();
    void undo();
}

// 3. 具体命令
class LightOnCommand implements Command {
    private Light light;
    public LightOnCommand(Light light) { this.light = light; }

    @Override
    public void execute() { light.turnOn(); }

    @Override
    public void undo() { light.turnOff(); }
}

// 4. 调用者(遥控器)
class RemoteControl {
    private Command command;
    private Stack<Command> history = new Stack<>();

    public void setCommand(Command cmd) { this.command = cmd; }

    public void pressButton() {
        command.execute();
        history.push(command);
    }

    public void pressUndo() {
        if (!history.isEmpty()) {
            Command lastCmd = history.pop();
            lastCmd.undo();
        }
    }
}

// 5. 客户端调用
public class Client {
    public static void main(String[] args) {
        Light light = new Light();
        Command cmd = new LightOnCommand(light);

        RemoteControl remote = new RemoteControl();
        remote.setCommand(cmd);

        remote.pressButton(); // 开灯
        remote.pressUndo();   // 关灯(撤销)
    }
}

四、工业级源码应用

  1. Java Swing事件处理
  • 每个按钮点击事件(ActionListener)本质是命令对象,将GUI操作与业务逻辑解耦。
button.addActionListener(e -> service.doSomething()); // Lambda表达式封装命令
  1. Spring框架事务管理
    • @Transactional注解通过AOP生成事务命令对象,封装数据库的commit/rollback操作。
  1. MyBatis Mapper接口
    • 动态代理生成Mapper接口的实现类,将SQL执行封装为命令对象。
  1. 文本编辑器撤销功能
    • 如IntelliJ IDEA通过UndoManager维护命令栈,支持多级撤销。
  1. 游戏引擎技能系统
    • 魔兽世界的技能快捷键绑定命令对象,支持技能队列与取消施法。

五、模式对比与最佳实践

维度 命令模式 策略模式
关注点 请求封装与生命周期管理 算法替换
核心价值 解耦调用与执行,支持事务 动态切换行为策略
典型场景 撤销/重做、异步队列 支付方式选择、排序算法

最佳实践建议

  1. 轻量化命令对象:避免在命令中存储过多状态(优先使用接收者状态)。
  2. 组合命令:通过MacroCommand实现批处理操作。
  3. 线程安全:多线程环境下需对命令队列加锁(如BlockingQueue)。

总结

命令模式通过操作对象化的设计哲学,在GUI框架、事务系统等领域展现出强大的灵活性。其核心价值在于将请求的发起与执行分离,使得系统能够优雅地支持撤销、重做、事务管理等高级特性。开发者应重点把控命令对象的生命周期状态管理,结合具体场景选择静态代理或动态代理实现方式,从而构建出高扩展、易维护的系统架构。

posted @ 2025-04-12 10:52  雾里看花的少年  阅读(47)  评论(0)    收藏  举报