目录
1、核心思想
2、实现方式
2.1 模式结构
2.2 实现案例
3、优缺点分析
4、适用场景
5、实际应用
1、核心思想
目的:将指令信息封装成一个对象,并将此对象作为参数发送给接收方去执行,以使命令的请求方与执行方解耦
概念:命令是一个对象向另一个或多个对象发送的指令信息。命令的发送方负责下达指令,接收方则根据命令触发相应的行为。
举例:
1> 遥控器对电视机发出的换台、调音量等指令
2> 将军针对士兵执行进攻、撤退或者先退再进的任务所下达的一系列命令
3> 餐厅中顾客为了让厨师按照自己的需求烹饪所需的菜品,需要与服务员确定的点菜单
4> 数据库的增、删、改、查:用户会向数据库发送SQL语句来执行相关操作,或提交回滚操作
2、实现方式
2.1 模式结构
五个核心角色:
- Receiver(命令执行方):最终的命令执行方
- Command(命令接口):定义命令执行的接口标准,可包括执行与反向执行操作。
- ConcreteCommand(命令实现):命令接口的实现类,可以有任意多个,持有执行方对象的引用,其方法中调用命令执行方所对应的执行方法。
- Invoker(命令请求方):命令的请求方或发送方,持有命令接口的引用,并控制命令的执行或反向执行操作。
- Client(客户端):创建命令对象并关联接收者和调用者。
2.2 实现案例
遥控器控制家电:
// 1、命令执行方
// 电灯
public class Light {
public void on() {
System.out.println("电灯已打开");
}
public void off() {
System.out.println("电灯已关闭");
}
}
// 风扇
public class Fan {
public void on() {
System.out.println("风扇已启动");
}
public void off() {
System.out.println("风扇已停止");
}
}
// 2、命令接口
public interface Command {
void execute(); // 执行操作
void undo(); // 撤销操作
}
// 3、命令实现
// 开灯命令
public 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(); // 撤销操作即关灯
}
}
// 关灯命令
public 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(); // 撤销操作即开灯
}
}
// 省略开风扇命令FanOnCommand、关风扇命令FanOffCommand
// 4、命令请求方:遥控器
public class RemoteControl {
private Command command;
private Stack<Command> history = new Stack<>(); // 记录操作历史
public void setCommand(Command command) {
this.command = command;
}
// 执行命令并记录历史
public void pressButton() {
command.execute();
history.push(command);
}
// 撤销上一次操作
public void pressUndo() {
if (!history.isEmpty()) {
Command lastCommand = history.pop();
lastCommand.undo();
}
}
}
// 5、客户端
public class Client {
public static void main(String[] args) {
Light light = new Light();
Fan fan = new Fan();
// 创建命令对象
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
Command fanOn = new FanOnCommand(fan);
Command fanOff = new FanOffCommand(fan);
// 配置遥控器按钮
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // 输出:电灯已打开
remote.pressUndo(); // 输出:电灯已关闭(撤销)
remote.setCommand(fanOn);
remote.pressButton(); // 输出:风扇已启动
remote.setCommand(fanOff);
remote.pressButton(); // 输出:风扇已停止
remote.pressUndo(); // 输出:风扇已启动(撤销)
}
}
3、优缺点分析
优点:
-
解耦请求发送者与接收者:调用者无需知道接收者的具体实现。
-
支持撤销/重做:通过记录命令历史实现操作回退。
-
灵活扩展命令:新增命令无需修改现有代码。
-
支持宏命令:可组合多个命令为一个复合操作。
缺点:
-
类数量增加:每个操作需一个具体命令类。
-
复杂度提升:需要处理命令参数和状态管理。
4、适用场景
-
需要撤销/重做功能
-
如文本编辑器的撤销操作、事务回滚。
-
-
异步任务队列
-
将命令存入队列,延迟或按序执行。
-
-
GUI操作与业务逻辑解耦
-
如按钮点击事件绑定不同命令。
-
-
日志记录与恢复
-
记录所有执行的命令,用于系统恢复。
-
5、实际应用
-
Java Swing的Action接口
javax.swing.Action
是命令模式的典型实现,用于处理按钮、菜单项的操作。 -
线程池任务队列
将
Runnable
或Callable
对象作为命令提交到线程池执行。 -
数据库事务
每个SQL操作封装为命令对象,支持事务提交或回滚。