命令模式

行为型模式

访问次数: 10

命令模式将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

类图
classDiagram
    class Command {
        <<interface>>
        +execute()
        +undo()
    }
    class ConcreteCommand {
        -receiver: Receiver
        +execute()
        +undo()
    }
    class Receiver {
        +action()
    }
    class Invoker {
        -command: Command
        +setCommand(command: Command)
        +executeCommand()
    }
    class Client {
        +createCommand()
    }
    Command <|-- ConcreteCommand
    ConcreteCommand --> Receiver
    Invoker --> Command
    Client --> ConcreteCommand
    Client --> Receiver
    Client --> Invoker
源代码示例
// 命令接口
interface Command {
    void execute();
    void undo();
}

// 接收者
class Receiver {
    public void action() {
        System.out.println("Receiver action");
    }
}

// 具体命令
class ConcreteCommand implements Command {
    private Receiver receiver;
    
    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }
    
    @Override
    public void execute() {
        receiver.action();
    }
    
    @Override
    public void undo() {
        System.out.println("Undo action");
    }
}

// 调用者
class Invoker {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void executeCommand() {
        command.execute();
    }
}

// 客户端
class Client {
    public void createCommand() {
        Receiver receiver = new Receiver();
        Command command = new ConcreteCommand(receiver);
        Invoker invoker = new Invoker();
        
        invoker.setCommand(command);
        invoker.executeCommand();
    }
}
# Python代码待添加
应用场景
当需要将请求封装成对象,支持撤销操作、日志记录、队列化请求时。应用场景包括: 1)文本编辑器中的撤销/重做功能,将每个编辑操作封装成命令对象 2)宏命令的录制和回放,将一系列操作封装成宏命令 3)图形编辑器中的操作历史,支持撤销和重做图形操作 4)数据库事务管理,将数据库操作封装成命令对象,支持事务回滚 5)游戏中的操作记录,记录玩家的操作序列,支持回放和撤销 6)批处理系统,将多个操作封装成批处理命令,支持批量执行和回滚
精选场景详解 —— 文本编辑器:撤销 / 重做操作历史
问题背景

编辑器支持输入、删除、粘贴。用户需要 Ctrl+Z / Ctrl+Y。若只改文档缓冲区而不记录操作,无法可靠回滚。

模式如何解决
选用命令模式:把每次编辑封装为 Command(execute/undo)。Invoker(编辑器 UI)执行命令并将其压入历史栈;撤销时 pop 并 undo,重做再 execute。 收益: 1)请求者与接收者(Document)解耦; 2)天然支持队列、日志、宏命令(一组命令组合); 3)可序列化命令做操作审计。 这是命令模式最经典的教学与实战场景之一。
场景模型(角色映射)

将模式中的抽象角色映射到该业务领域的具体类:

classDiagram
    class Command {
        <<interface>>
        +execute()
        +undo()
    }
    class InsertTextCommand {
        -doc: Document
        -pos: int
        -text: String
        +execute()
        +undo()
    }
    class DeleteTextCommand {
        -doc: Document
        -pos: int
        -len: int
        +execute()
        +undo()
    }
    class Document {
        +insert(pos: int, text: String)
        +delete(pos: int, len: int)
    }
    class EditorInvoker {
        -history: Stack~Command~
        -redo: Stack~Command~
        +run(cmd: Command)
        +undo()
        +redo()
    }
    Command <|.. InsertTextCommand
    Command <|.. DeleteTextCommand
    InsertTextCommand --> Document
    DeleteTextCommand --> Document
    EditorInvoker --> Command