命令模式 (Command)
📖 通俗理解
去餐厅吃饭:
- 你告诉服务员:我要一份宫保鸡丁
- 服务员把订单写到纸上
- 服务员把订单交给厨师
- 厨师按照订单做菜
订单就是一个命令!它把"点菜请求"封装成了一个对象。
命令模式就是:将请求封装成对象,从而可以用不同的请求进行参数化。
🎯 解决什么问题?
- 将请求发送者和接收者解耦
- 支持撤销、重做、队列、日志等功能
- 可以组合多个命令
🌰 生活中的例子
- 餐厅点菜:订单就是命令
- 遥控器:每个按钮对应一个命令
- 事务操作:命令可以回滚
💻 Java 代码实现
场景:智能家居遥控器
/**
* 命令接口
*/
public interface Command {
void execute();
void undo();
}
/**
* 接收者:灯
*/
public class Light {
private String location;
public Light(String location) {
this.location = location;
}
public void on() {
System.out.println(location + "灯打开了 💡");
}
public void off() {
System.out.println(location + "灯关闭了");
}
}
/**
* 具体命令:开灯
*/
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();
}
}
/**
* 调用者:遥控器
*/
public class RemoteControl {
private Command[] onCommands;
private Command[] offCommands;
private Command lastCommand;
public RemoteControl() {
onCommands = new Command[5];
offCommands = new Command[5];
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonPressed(int slot) {
if (onCommands[slot] != null) {
onCommands[slot].execute();
lastCommand = onCommands[slot];
}
}
public void offButtonPressed(int slot) {
if (offCommands[slot] != null) {
offCommands[slot].execute();
lastCommand = offCommands[slot];
}
}
public void undoButtonPressed() {
if (lastCommand != null) {
System.out.println("撤销上一步操作...");
lastCommand.undo();
}
}
}
使用:
public class Client {
public static void main(String[] args) {
// 创建接收者
Light livingRoomLight = new Light("客厅");
Light bedroomLight = new Light("卧室");
// 创建命令
Command livingRoomOn = new LightOnCommand(livingRoomLight);
Command livingRoomOff = new LightOffCommand(livingRoomLight);
Command bedroomOn = new LightOnCommand(bedroomLight);
Command bedroomOff = new LightOffCommand(bedroomLight);
// 配置遥控器
RemoteControl remote = new RemoteControl();
remote.setCommand(0, livingRoomOn, livingRoomOff);
remote.setCommand(1, bedroomOn, bedroomOff);
// 使用遥控器
remote.onButtonPressed(0); // 开客厅灯
remote.onButtonPressed(1); // 开卧室灯
remote.offButtonPressed(0); // 关客厅灯
remote.undoButtonPressed(); // 撤销:重新开客厅灯
}
}
输出:
客厅灯打开了 💡
卧室灯打开了 💡
客厅灯关闭了
撤销上一步操作...
客厅灯打开了 💡
🔥 宏命令(组合命令)
/**
* 宏命令:一键执行多个命令
*/
public class MacroCommand implements Command {
private Command[] commands;
public MacroCommand(Command[] commands) {
this.commands = commands;
}
@Override
public void execute() {
for (Command command : commands) {
command.execute();
}
}
@Override
public void undo() {
for (int i = commands.length - 1; i >= 0; i--) {
commands[i].undo();
}
}
}
// 使用:一键关闭所有设备
Command[] partyOff = { lightOff, tvOff, stereoOff };
MacroCommand partyOffMacro = new MacroCommand(partyOff);
partyOffMacro.execute();
✅ 适用场景
- 需要撤销/重做功能:文本编辑器
- 需要将操作排队:任务队列
- 需要记录操作日志:数据库事务
小结
命令模式:将请求封装成对象,支持撤销、排队、日志等功能。
核心角色:命令(Command)、调用者(Invoker)、接收者(Receiver)
👉 下一篇:解释器模式
