一、基本介绍
命令模式(行为型):将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开(解耦)。
二、包含角色
1.抽象命令角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
2.具体命令角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
3.接收者:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
4.调用者:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
三、案例及UML类图
案例说明:
使用遥控器操纵灯泡,有两个命令,开灯或关灯,遥控器是调用者,发送命令,灯泡是命令接受者,执行命令,开灯和关灯是具体命令。
UML类图:
类Command:
public interface Command {
/**
* 执行命令
*/
void execute();
}
说明:抽象命令类,抽象命令角色,定义了命令的公共接口。
类OnCommand:
public class OnCommand implements Command {
//命令接收者
private LightReceiver lightReceiver;
public OnCommand(LightReceiver lightReceiver) {
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
lightReceiver.on();
}
}
说明:开灯命令类,具体命令角色,调用命令接收者开灯操作。
类OffCommand:
public class OffCommand implements Command {
//命令接收者
private LightReceiver lightReceiver;
public OffCommand(LightReceiver lightReceiver) {
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
lightReceiver.off();
}
}
说明:关灯命令类,具体命令角色,调用命令接收者关灯操作。
类RemoteControl:
public class RemoteControl {
private Command command;
/**
* 设置当前要执行的命令
* @param command 命令
*/
public void setCommand(Command command) {
this.command = command;
}
/**
* 执行当前命令
*/
public void executeCommand() {
command.execute();
}
}
说明:遥控器类,调用者角色,通过设置要执行的命令,并调用命令的执行方法,与命令接收者隔离。
类LightReceiver:
public class LightReceiver {
public void on() {
System.out.println("开灯!");
}
public void off() {
System.out.println("关灯!");
}
}
说明:灯泡类,命令接收者,真正执行命令的类。
类CommandTest:
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
LightReceiver lightReceiver = new LightReceiver();
remoteControl.setCommand(new OnCommand(lightReceiver));
remoteControl.executeCommand();
remoteControl.setCommand(new OffCommand(lightReceiver));
remoteControl.executeCommand();
}
说明:测试及客户端类。
四、适用场景
1.当系统需要将请求调用者与请求接收者解耦时,命令模式使得调用者和接收者不直接交互。
2.当系统需要执行一组操作时,命令模式可以定义宏命令(即一系列命令)来实现该功能。
3.当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时
五、其它
注意:
1.命令模式变种很多,本文只列举最基本的一种。
2.命令模式可以有多个接收者,也可以一个命令对应一个接收者或同一个接口的接收者,这样有利于拓展,但可能会产生类爆炸问题,具体根据业务情况判断。
3.命令模式有仅有一个接收者时,该接收者类可有可无,如果不写接收者类,在命令中直接调用具体的命令操作即可。
4.命令模式可用于宏命令操作,添加多个命令,一起执行。
5.在很多地方命令模式用于doit和undo操作,即操作和恢复操作。