定义
将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作
要点
- 命令模式将发出请求的对象和执行请求的对象解耦
- 在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者的一个或一组动作
- 调用者可以接收命令当作参数,甚至在运行的时候动态进行
- 命令可以被撤销,做法是实现一个
undo()
方法来回到execute()
被执行前的状态 - 宏命令是命令的一种简单延申,允许调用多个命令。宏方法也可以支持撤销。
案例
- 定义一个命令接口Command,里面有执行命令和撤销命令两个方法
public interface Command {
//执行命令
void execute();
//撤销命令
void undo();
}
- 定义一个接收者对象,用来完成自己的动作
public class Receiver {
public void sendData(){
System.out.println("发送数据");
}
public void cancelSend(){
System.out.println("取消发送");
}
}
- 实现一个命令并将接收者对象用组合的方式跟命令绑定到一起,请求者只需执行此命令而并不用知道接收者具体要做什么,这样的话,请求者和接收者之间就解除了耦合
public class ReceiverCommand implements Command {
private Receiver receiver;
public ReceiverCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.sendData();
}
@Override
public void undo() {
receiver.cancelSend();
}
}
- 将命令与请求者进行绑定
public class RequestManager {
Command command;
public void setCommand(Command onCommand) {
this.command = onCommand;
}
public void executeCommand(){
this.command.execute();
}
public void undoCommand(){
this.command.undo();
}
}
通过一个setCommand()
方法可以将任何实现了Command接口的命令和请求者绑定起来,这样请求者就可以执行不同的命令,从而让不同的命令去做出不同的动作,而具体做什么是由被封装到命令中的接收者对象去完成的,因此请求者是不知道接收者具体要做什么的。
- 最后测试一下
public class CommandTest {
public static void main(String[] args){
Receiver receiver = new Receiver();
ReceiverCommand receiverCommand = new ReceiverCommand(receiver);
RequestManager requestManager = new RequestManager();
requestManager.setCommand(receiverCommand);
requestManager.executeCommand();
requestManager.undoCommand();
}
}
- 打印结果
发送数据
取消发送
宏命令
上面只是定义了一个命令,实际情况中,我们可能会执行一组命令,也就是宏命令。我们来修改RequestManager
类,让它可以接收一组命令,代码如下:
public class RequestManager {
Command[] commands;
public void setCommand(Command[] commands) {
this.commands = commands;
}
public void executeCommand(){
for (Command command : commands) {
command.execute();
}
}
public void undoCommand(){
for (Command command : commands) {
command.undo();
}
}
}
将Command声明成数组用来接收一组命令,然后在执行请求的时候去遍历所有的命令执行它们的execute()
和undo()
方法,这样便完成了一组命令的执行。
网友评论