命令模式(Command Pattern)

命令模式(Command Pattern)

命令模式是一种行为型设计模式,它将「请求」封装为对象,从而实现请求发送者(Invoker)与请求接收者(Receiver)的完全解耦,并支持撤销、重做、排队、日志记录等扩展能力。


一、命令模式的核心概念

命令模式的核心思想是:将请求抽象成独立的命令对象,使得请求可以被存储、传递、排队、撤销或组合。

主要角色包括:

角色 职责
Command(命令接口) 声明执行操作的接口
ConcreteCommand(具体命令) 实现命令接口,绑定接收者并调用其方法
Receiver(接收者) 真正执行命令的对象
Invoker(调用者) 持有命令对象并触发执行
Client(客户端) 创建命令对象并设置接收者

二、命令模式解决的问题

命令模式主要解决:

  1. 请求者与执行者之间的紧耦合(例如 GUI 按钮与业务逻辑)。
  2. 需要支持撤销/重做、事务、日志记录等场景。
  3. 需要将操作排队、组合成宏命令或延迟执行。

三、适用场景

命令模式适用于:

  • GUI 中按钮、菜单项触发的操作。
  • 需要撤销/重做的编辑器、IDE、绘图软件。
  • 事务系统、操作日志回放。
  • 遥控器控制家电、游戏指令、机器人指令等。

四、命令模式的优缺点

✅ 优点

  • 完全解耦调用者与接收者。
  • 易扩展:新增命令无需修改现有代码。
  • 支持撤销/重做、事务、日志、队列等高级功能。

❌ 缺点

  • 命令类数量可能过多,导致系统复杂度上升。
  • 间接调用带来一定性能开销。

五、命令模式结构图(文字版)

复制代码
Client           → 创建命令对象并设置接收者
Invoker          → 持有命令对象并触发执行
Command          → 抽象命令接口
ConcreteCommand  → 实现命令并调用 Receiver
Receiver         → 执行实际操作

六、典型代码示例(简化版)

1. 命令接口

java 复制代码
public interface Command {
    void execute();
}

2. 接收者

java 复制代码
public class Receiver {
    public void action() {
        System.out.println("执行具体操作");
    }
}

3. 具体命令

java 复制代码
public class ConcreteCommand implements Command {
    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    public void execute() {
        receiver.action();
    }
}

4. 调用者

java 复制代码
public class Invoker {
    private Command command;

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

    public void executeCommand() {
        command.execute();
    }
}

5. 客户端

java 复制代码
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();

七、时序图

接收者 Receiver 具体命令 ConcreteCommand 调用者 Invoker 客户端 Client 接收者 Receiver 具体命令 ConcreteCommand 调用者 Invoker 客户端 Client #mermaid-svg-9P7nYhK6TKwR4ZVL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9P7nYhK6TKwR4ZVL .error-icon{fill:#552222;}#mermaid-svg-9P7nYhK6TKwR4ZVL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9P7nYhK6TKwR4ZVL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9P7nYhK6TKwR4ZVL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9P7nYhK6TKwR4ZVL .marker.cross{stroke:#333333;}#mermaid-svg-9P7nYhK6TKwR4ZVL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9P7nYhK6TKwR4ZVL p{margin:0;}#mermaid-svg-9P7nYhK6TKwR4ZVL .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9P7nYhK6TKwR4ZVL text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-9P7nYhK6TKwR4ZVL .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-9P7nYhK6TKwR4ZVL .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-9P7nYhK6TKwR4ZVL #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-9P7nYhK6TKwR4ZVL .sequenceNumber{fill:white;}#mermaid-svg-9P7nYhK6TKwR4ZVL #sequencenumber{fill:#333;}#mermaid-svg-9P7nYhK6TKwR4ZVL #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-9P7nYhK6TKwR4ZVL .messageText{fill:#333;stroke:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9P7nYhK6TKwR4ZVL .labelText,#mermaid-svg-9P7nYhK6TKwR4ZVL .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .loopText,#mermaid-svg-9P7nYhK6TKwR4ZVL .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-9P7nYhK6TKwR4ZVL .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-9P7nYhK6TKwR4ZVL .noteText,#mermaid-svg-9P7nYhK6TKwR4ZVL .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-9P7nYhK6TKwR4ZVL .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9P7nYhK6TKwR4ZVL .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9P7nYhK6TKwR4ZVL .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9P7nYhK6TKwR4ZVL .actorPopupMenu{position:absolute;}#mermaid-svg-9P7nYhK6TKwR4ZVL .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-9P7nYhK6TKwR4ZVL .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9P7nYhK6TKwR4ZVL .actor-man circle,#mermaid-svg-9P7nYhK6TKwR4ZVL line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-9P7nYhK6TKwR4ZVL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建接收者 new Receiver()1创建命令 new ConcreteCommand(receiver)2创建调用者 new Invoker()3setCommand(command)4executeCommand()5execute()6action()7


八、总结

命令模式通过将请求封装为对象,实现了请求发送者与执行者的彻底解耦,并天然支持撤销、重做、事务、日志等高级功能,是行为型设计模式中非常重要的一种。


相关推荐
SabrinaW7113 天前
命令模式思想与 EvSim 事件调度
命令模式
加载力科技19 天前
Mac 打开 ISO 文件完整教程:3 种方法挂载与解压,挂载失败也能提取文件
macos·命令模式·磁盘工具·mac打开iso·hdiutil·iso解压·mac技巧
lingchen19061 个月前
Windows CMD 的 `cd`(change directory,切换目录)命令
windows·命令模式
Lost of 程序猿1 个月前
命令模式实战:把“下单后的动作“打包成可执行的任务
后端·设计模式·c#·asp.net·命令模式
加载力科技1 个月前
硬盘咔咔响是坏盘信号!赶在数据丢失前克隆换盘:不重装系统、不丢文件
windows·嵌入式硬件·系统安全·策略模式·命令模式·硬盘
czhc11400756632 个月前
2026-09-10 综合博客:异步异常 + 排查核实思维
命令模式
geovindu2 个月前
CSharp: Command Pattern
开发语言·后端·c#·.net·.netcore·命令模式·行为模式
Java后端的Ai之路2 个月前
21、Python - 命令模式
开发语言·人工智能·python·命令模式·外观模式
Flutter OH2 个月前
Flutter OH 卡死冻屏问题定位指南
flutter·命令模式