概念
将请求封装为对象,从而使得不同的请求可以被参数化、排队、记录日志,并支持撤销和恢复操作。通过这种方式,命令的发送者与接收者之间实现了解耦
应用场景
在需要解耦请求发送者和接收者时
命令不需要立刻执行,或需要参数化、排队、记录日志时

避免了硬编码与命令立刻执行的弊端
基本结构

1)命令接口(Command):声明执行操作的方法,比如execute()
2)具体命令(ConcreteCommand):实现命令接口,负责调用接收者(Receiver)去完成请求
3)接收者(Receiver):真正执行具体业务逻辑的人(类)
4)请求者(Invoker):负责调用命令对象来执行请求
5)客户端(Client):创建具体命令对象并设置好接收者,最后把命令交给请求者执行
代码实现
以”电灯开关“为例
接收者
真正执行命令的实体,根据命令做出具体的反应
public class Light {
void turnOn() {
System.out.println("Light is on");
}
void turnOff() {
System.out.println("Light is off");
}
}
命令接口
所有任务的统一接口
public interface Command {
void execute();
}
具体命令
具体命令中包含接受者,表示该任务将由该接受者执行
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
请求者(任务调度器)
包含了命令(可以用队列维护)与执行方法pressButton()
public 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 livingRoomLight = new Light();
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
RemoteControl remote = new RemoteControl();
remote.setCommand(livingRoomLightOn);
remote.pressButton(); // 打开电灯
remote.setCommand(livingRoomLightOff);
remote.pressButton(); // 关闭电灯
}
}
优缺点
优点
1)解耦请求者和执行者:将请求和执行操作分离
2)能够维护命令:命令不会立刻执行,能够记录、撤销、恢复命令
3)便于新增命令:符合开闭原则
