Java命令模式
命令模式将请求封装为对象,支持请求排队、撤销、重做。
模式定义
意图:将请求封装为对象,使请求发送者与接收者解耦。
适用场景
- 需要将请求参数化
- 需要支持撤销/重做
- 需要记录请求日志
- 需要事务操作
模式结构
命令接口
Java
public interface Command {
void execute();
void undo(); // 撤销
}
接收者
Java
public class Light {
public void on() {
System.out.println("灯打开");
}
public void off() {
System.out.println("灯关闭");
}
}
具体命令
Java
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();
}
}
调用者
Java
public class RemoteControl {
private Command command;
private Command lastCommand; // 记录最后命令,用于撤销
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
lastCommand = command;
}
public void pressUndo() {
if (lastCommand != null) {
lastCommand.undo();
}
}
}
使用示例
Java
Light light = new Light();
RemoteControl remote = new RemoteControl();
remote.setCommand(new LightOnCommand(light));
remote.pressButton(); // 灯打开
remote.setCommand(new LightOffCommand(light));
remote.pressButton(); // 灯关闭
remote.pressUndo(); // 灯打开(撤销关闭)
命令队列
Java
public class CommandQueue {
private List<Command> commands = new ArrayList<>();
public void addCommand(Command command) {
commands.add(command);
}
public void executeAll() {
for (Command command : commands) {
command.execute();
}
commands.clear();
}
}
宏命令
Java
public class MacroCommand implements Command {
private List<Command> commands = new ArrayList<>();
public void addCommand(Command command) {
commands.add(command);
}
@Override
public void execute() {
for (Command command : commands) {
command.execute();
}
}
@Override
public void undo() {
for (int i = commands.size() - 1; i >= 0; i--) {
commands.get(i).undo();
}
}
}
// 使用:一键执行多个命令
MacroCommand macro = new MacroCommand();
macro.addCommand(new LightOnCommand(light1));
macro.addCommand(new LightOnCommand(light2));
macro.addCommand(new TVOnCommand(tv));
macro.execute(); // 所有设备打开
撤销重做实现
Java
public class UndoRedoManager {
private Stack<Command> undoStack = new Stack<>();
private Stack<Command> redoStack = new Stack<>();
public void execute(Command command) {
command.execute();
undoStack.push(command);
redoStack.clear();
}
public void undo() {
if (!undoStack.isEmpty()) {
Command command = undoStack.pop();
command.undo();
redoStack.push(command);
}
}
public void redo() {
if (!redoStack.isEmpty()) {
Command command = redoStack.pop();
command.execute();
undoStack.push(command);
}
}
}
实际应用示例
文本编辑器
Java
public interface TextCommand {
void execute();
void undo();
}
public class InsertCommand implements TextCommand {
private StringBuilder text;
private String inserted;
private int position;
public InsertCommand(StringBuilder text, String inserted, int position) {
this.text = text;
this.inserted = inserted;
this.position = position;
}
@Override
public void execute() {
text.insert(position, inserted);
}
@Override
public void undo() {
text.delete(position, position + inserted.length());
}
}
// 使用
StringBuilder text = new StringBuilder("Hello");
UndoRedoManager manager = new UndoRedoManager();
manager.execute(new InsertCommand(text, " World", 5));
System.out.println(text); // "Hello World"
manager.undo();
System.out.println(text); // "Hello"
命令模式优点
- 解耦请求发送者与执行者
- 支持撤销/重做
- 支持命令排队和日志
- 新增命令不影响现有代码
注意事项
命令类数量可能很多
撤销需记录足够状态信息
命令应尽量轻量,避免复杂逻辑
GUI按钮、菜单项操作是典型应用
要点总结
- 命令模式将请求封装为对象,解耦调用者与接收者
- Command接口定义execute()和undo()
- Invoker持有命令对象,负责调用
- 支持撤销重做、命令队列、宏命令
- GUI操作、事务处理是典型应用场景
📝 发现内容有误?点击此处直接编辑