基本概念
命令模式:一种行为型设计模式,它将“请求”封装为对象,使发送请求的客户端与执行请求的接收者解耦。通过这种封装,可以让请求参数化、排队执行、记录日志或支持撤销操作。
核心结构
- 命令接口(
Command
):定义执行命令的方法(如execute())。
- 具体命令(
Concrete Command
):实现命令接口,绑定接收者和具体操作。
- 接收者(
Receiver
):执行命令的具体对象,知道如何完成命令对应的操作。
- 调用者(
Invoker
):持有命令对象,通过调用命令的方法来触发请求。
- 客户端(
Client
):创建具体命令并设置其接收者,将命令交给调用者。
示例说明
场景:遥控器控制家电
- 命令接口
1 2 3 4 5 6 7
|
interface Command { void execute(); void undo(); }
|
- 接收者:电灯
1 2 3 4 5 6 7 8 9 10 11
| class Light { void on() { System.out.println("电灯开启"); } void off() { System.out.println("电灯关闭"); } }
|
- 接收者:电视
1 2 3 4 5 6 7 8 9 10 11
| class TV { void on() { System.out.println("电视开启"); } void off() { System.out.println("电视关闭"); } }
|
- 开灯命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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(); } }
|
- 关灯命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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(); } }
|
- 调用者:遥控器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); } public void pressUndoButton() { command.undo(); } }
|
- 测试验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Test { public static void main(String[] args) { Light light = new Light(); TV tv = new TV(); Command lightOn = new LightOnCommand(light); Command lightOff = new LightOffCommand(light); Command tvOn = new LightOnCommand(tv); RemoteControl remote = new RemoteControl(); remote.setCommand(lightOn); remote.pressButton(); remote.setCommand(lightOff); remote.pressButton(); remote.pressUndoButton(); } }
|
命令对象通过特定接收者上绑定一组动作来封装请求。要达到这一点,它把动作和接收者包进一个对象中,该对象仅暴露可执行的方法execute()
或undo()
,当被调用时,调用者无法知道具体内部做了什么操作,目的已经达到。
其类图如下:

总结
优点
- 解耦发送者与接收者:客户端无需知道谁执行命令,调用者无需知道命令的具体实现。
- 支持撤销操作:通过undo()方法可实现命令回滚(如文本编辑的撤销)。
- 支持日志和事务:命令执行可记录日志,便于故障恢复或事务管理。
- 扩展性强:新增命令只需创建新的具体命令类,符合开闭原则。
缺点
- 类数量增加:每个命令都需要独立的类,可能导致类爆炸。
- 复杂度上升:简单场景下使用命令模式可能过度设计。
使用场景
- 需要支持撤销/重做:如文本编辑器、绘图软件的操作历史。
- 需要命令排队或调度:如任务调度系统、线程池中的任务封装。
- 需要记录操作日志:如银行系统的交易记录,便于故障恢复。
- 需要将请求参数化:如GUI框架中按钮点击事件的处理(按钮是调用者,点击是命令)。
- 多线程场景:命令可作为独立任务提交给线程池执行。