命令模式 (Command)
场景问题
问题案例
考虑一个遥控器控制家电的场景,用户可以对灯、电视等设备进行开关操作,并且希望支持操作的撤销和记录。
不用模式的解决方案
实现简化版本
最直接的做法是遥控器直接调用家电的方法:
public class Light {
public void on() { System.out.println("灯打开"); }
public void off() { System.out.println("灯关闭"); }
}
public class RemoteControl {
private Light light;
public RemoteControl(Light light) { this.light = light; }
public void pressOn() { light.on(); }
public void pressOff() { light.off(); }
}
使用示例
Light light = new Light();
RemoteControl remote = new RemoteControl(light);
remote.pressOn();
remote.pressOff();
有何问题
- 遥控器与具体家电耦合,扩展性差。
- 难以支持操作记录、撤销等功能。
- 新增设备需修改遥控器代码。
解决方案
命令模式的定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录日志,以及支持可撤销的操作。
应用命令模式的思路
- 定义命令接口,具体命令实现该接口。
- 命令对象持有接收者引用,调用接收者方法。
- 调用者持有命令对象,触发命令执行。
命令模式的结构
- Command:命令接口,定义执行方法。
- ConcreteCommand:具体命令,实现命令逻辑。
- Invoker:调用者,持有命令对象。
- Receiver:接收者,执行实际操作。
命令模式的实现
// 命令接口
public interface Command {
void execute();
}
// 接收者
public class Light {
public void on() { System.out.println("灯打开"); }
public void off() { System.out.println("灯关闭"); }
}
// 具体命令
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
public void execute() { light.on(); }
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) { this.light = light; }
public void execute() { light.off(); }
}
// 调用者
public class RemoteControl {
private Command command;
public void setCommand(Command command) { this.command = command; }
public void pressButton() { command.execute(); }
}
使用示例
public class Client {
public static void main(String[] args) {
Light light = new Light();
Command on = new LightOnCommand(light);
Command off = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(on);
remote.pressButton();
remote.setCommand(off);
remote.pressButton();
}
}
命令重写示例
示例结构
示例代码
见上文"命令模式的实现"部分。
模式讲解
命令模式的功能
- 解耦请求发送者和接收者。
- 支持操作记录、撤销、排队等功能。
- 扩展新命令灵活。
实现成接口
- 命令接口通常定义为接口或抽象类。
使用工厂方法
- 可结合工厂方法模式,统一创建命令对象。
切换产品簇
- 可用于切换不同的命令族,如不同家电命令。