Java设计模式——命令模式
⚪命令模式(Command)是一种行为型设计模式,
⚪意图:它将一个请求或操作封装成一个对象,从而允许将客户端参数化操作、队列操作或记录日志,以及支持可撤销的操作。
⚪以下是工厂方法模式的关键要点:
▷ 角色和责任:
- 命令接口(Command):定义了执行特定操作的接口,通常包含一个 execute 方法。
- 具体命令(ConcreteCommand):实现了命令接口,封装了一个接收者对象和执行操作的方法。
- 接收者(Receiver):执行实际工作的对象,命令对象将请求传递给接收者来执行操作。
- 调用者(Invoker):负责将命令对象发送给接收者,可以存储一系列命令对象,实现一些高级功能,如撤销、重做或宏命令。
- 客户端(Client):创建具体命令对象并将其分配给调用者,触发命令的执行。
▷ 工作流程:
- 客户端创建具体命令对象,并将其与接收者关联。
- 客户端将命令对象分配给调用者。
- 调用者存储命令对象,可以根据需要执行它们。
- 调用者调用命令对象的 execute 方法。
- 命令对象通知接收者执行操作。
▷ 示例
// 命令接口
interface Command {
void execute();
}
// 具体命令 - 打开灯
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
// 具体命令 - 关闭灯
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOff();
}
}
// 接收者 - 灯
class Light {
public void turnOn() {
System.out.println("灯已打开");
}
public void turnOff() {
System.out.println("灯已关闭");
}
}
// 调用者 - 遥控器
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
public class CommandPatternExample {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
// 按下打开灯的按钮
remote.setCommand(lightOn);
remote.pressButton();
// 按下关闭灯的按钮
remote.setCommand(lightOff);
remote.pressButton();
}
}
⚪适用性
- 抽象出待执行的动作以参数化某对象。Command 模式是过程语言中的回调(Callback)机制的一个面向对象的替代品。
- 在不同的时刻指定、排列和执行请求。一个 Command 对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可以将负责该请求的命令对象传递给另一个不同的进程并在那儿实现该请求。
- 支持取消操作。Command 的 Execute 操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command 接口必须添加一个 Unexecute 操作,该操作取消上一次 Exccute 调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用Unexecute和Execute 来实现重数不限的“取消和“”。
- 支持修改日志。这样当系统崩溃时,这些修改可以被重做一遍。在 Command 接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用 Execute 操作重新执行它们。
- 用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务(Transaction)的信息系统中很常见。Command 模式提供了对事务进行建模的方法。Command 有一个公共接口,使得可以用同一种方式调用所有的事务,同时使用该模式也易于添加新事务以扩展系统。
⚪应用场景
- 遥控器:如前面的示例所示,命令模式常用于创建遥控器或控制面板,其中每个按钮都代表一个命令,以便执行不同的操作,例如打开电视、切换频道等。
- 任务队列:命令模式可以用于创建任务队列,允许将请求封装为命令并按顺序执行,这在异步任务处理中很有用。
- 编辑器操作:在文本编辑器或图形编辑器中,命令模式可以用于实现撤销、重做和记录操作历史的功能。
- 数据库事务:命令模式可用于实现数据库事务,将一系列数据库操作封装为一组命令,以确保它们要么全部成功,要么全部失败。
- 菜单和按钮:在图形用户界面中,可以使用命令模式将菜单项和按钮与操作关联起来。
⚪实际已有场景
- Java多线程:在多线程编程中,可以使用命令模式来表示要在不同线程中执行的任务。例如,Runnable 接口就是一个命令模式的应用,它允许您封装任务并将其传递给线程执行。
- Spring AOP(面向切面编程):Spring AOP使用代理模式来实现切面,而切面通常包含了各种通知(Advice),这些通知可以视为命令,它们在方法执行前、后或抛出异常时执行特定操作。
- Spring Boot:Spring Boot可以使用命令模式的思想来处理自定义命令行参数。您可以编写自己的命令,并注册它们,然后在应用程序启动时执行这些命令。
- Spring Integration:Spring Integration是一个用于构建企业级集成应用程序的Spring项目,它采用了事件驱动的方式,类似于命令模式,来处理消息和事件的传递和处理。