行为型:命令模式
目录
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;}@Overridepublic void execute() {light.on();}@Overridepublic void undo() {light.off(); // 撤销操作即关灯}
}// 关灯命令
public class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}@Overridepublic 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操作封装为命令对象,支持事务提交或回滚。