文章目录
- 前言
- 一、概念
- 二、核心结构
- [三、Java 代码实现(遥控器控制电视)](#三、Java 代码实现(遥控器控制电视))
-
- [1. 接收者(真正干活:TV)](#1. 接收者(真正干活:TV))
- [2. 抽象命令](#2. 抽象命令)
- [3. 具体命令:开机](#3. 具体命令:开机)
- [4. 具体命令:关机](#4. 具体命令:关机)
- [5. 调用者(遥控器)](#5. 调用者(遥控器))
- [6. 客户端使用](#6. 客户端使用)
- 四、命令模式的超强能力
- 五、优缺点
- 六、应用场景
- 七、总结
前言
日常开发中,我们常需要对行为进行封装 :比如按钮点击、菜单操作、事务回滚、任务延迟执行、操作记录、撤销/重做等。如果直接调用方法,会造成请求发起者与执行者强耦合 ,无法灵活控制行为。命令模式 正是将请求封装为对象,让你可以像传递对象一样管理、存储、延迟、撤销行为,是实现"操作可记录、可撤销、可排队"的核心行为型模式。
一、概念
命令模式(Command Pattern) 是一种行为型设计模式 ,核心思想:
将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队、记录日志、撤销操作。
简单理解:
- 把"方法调用"包装成一个对象(Command);
- 包含:执行、撤销(可选);
- 发送者只管发出命令,不关心谁执行、怎么执行;
- 接收者只管执行,不关心谁发来。
一句话:
行为封装成对象,可传、可存、可撤销、可排队。
二、核心结构
- Command(抽象命令)
定义执行、撤销接口。 - ConcreteCommand(具体命令)
绑定接收者,实现执行逻辑。 - Receiver(接收者)
真正执行业务的对象。 - Invoker(调用者/发送者)
持有命令,触发命令。 - Client(客户端)
创建命令、绑定接收者、交给调用者。
三、Java 代码实现(遥控器控制电视)
场景:遥控器按钮 → 控制电视 开/关/换台 ,支持撤销。
1. 接收者(真正干活:TV)
java
// 接收者:电视机
public class TV {
public void on() {
System.out.println("电视已打开");
}
public void off() {
System.out.println("电视已关闭");
}
public void changeChannel() {
System.out.println("切换频道");
}
}
2. 抽象命令
java
public interface Command {
void execute(); // 执行
void undo(); // 撤销
}
3. 具体命令:开机
java
public class TVOnCommand implements Command {
private TV tv;
public TVOnCommand(TV tv) { this.tv = tv; }
@Override
public void execute() { tv.on(); }
@Override
public void undo() { tv.off(); }
}
4. 具体命令:关机
java
public class TVOffCommand implements Command {
private TV tv;
public TVOffCommand(TV tv) { this.tv = tv; }
@Override
public void execute() { tv.off(); }
@Override
public void undo() { tv.on(); }
}
5. 调用者(遥控器)
java
// 调用者:遥控器
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
// 按下按钮
public void pressButton() {
command.execute();
}
// 按下撤销
public void pressUndo() {
command.undo();
}
}
6. 客户端使用
java
public class Client {
public static void main(String[] args) {
TV tv = new TV();
Command on = new TVOnCommand(tv);
Command off = new TVOffCommand(tv);
RemoteControl remote = new RemoteControl();
// 开机
remote.setCommand(on);
remote.pressButton();
remote.pressUndo(); // 撤销=关机
System.out.println("----------");
// 关机
remote.setCommand(off);
remote.pressButton();
remote.pressUndo(); // 撤销=开机
}
}
输出:
电视已打开
电视已关闭
----------
电视已关闭
电视已打开
四、命令模式的超强能力
- 队列请求:把命令放入队列,异步/定时执行
- 日志请求:记录所有命令,崩溃后重做
- 撤销/重做:存储执行栈,回滚操作
- 事务性:一组命令统一提交/回滚
- 宏命令:一键执行多个命令(组合模式+命令)
五、优缺点
优点
- 解耦发送者与接收者
- 易于扩展新命令(符合开闭)
- 支持撤销、排队、日志、事务
- 可组合宏命令
缺点
- 类爆炸:每个行为一个Command类
- 增加一层间接性,稍复杂
六、应用场景
- GUI按钮、菜单点击
- 事务、回滚、重做
- 延迟执行、异步任务
- 操作日志、审计
- 指令集、脚本执行
- 线程池、任务队列(Runnable 就是命令模式)
经典代表:
- Java Runnable/Callable
- Spring ApplicationEvent
- Git 提交/回滚
- 编辑器撤销(Ctrl+Z)
七、总结
- 命令模式 = 把行为封装成对象
- 核心:可执行、可撤销、可存储、可传递
- 结构:
Command+Receiver+Invoker - 最适合:需要控制、记录、延迟、撤销行为的场景