命令模式把请求封装成为命令对象,并定义统一的执行操作接口。这个命令对象可以被存储、转发、记录、处理、撤销等。
1、定义
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
2、使用场景
- 需要抽象出待执行的动作,然后以参数形式提供出来,类似于回调机制。
- 在不同的时刻指定、排列和执行请求。一个命令对象可以有与初始请求无关的生存期。
- 需要支持撤销
- 需要支持当系统崩溃时,能将系统的操作功能重新执行一遍。
- 当系统需要支持事务
3、UML图
- Command:定义命令的接口。
- ConcreteComand:命令接口实现者。是“虚”的实现,通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
- Invoker:请求者。它的职责就是调用命令对象执行具体的请求。
- Client:客户端。
4、示例代码
public interface Command {
/**
* * 执行命令
*/
public void execute();
/**
* 撤销命令
*/
public void undo();
}
public class ConcreteCommand implements Command {
//命令要求的功能的真正实现者
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
@Override
public void undo() {
receiver.unAction();
}
}
/**
* 命令接收者,命令真正执行人
*/
public class Receiver {
public void action() {
System.out.println("执行命令...");
}
public void unAction() {
System.out.println("撤销命令...");
}
}
public class Invoker {
/**
* 调用者持有命令对象
*/
private Command command;
public void setCommand(Command command) {
this.command = command;
}
/**
* 执行命令
*/
public void runCommand() {
command.execute();
}
/**
* 撤销命令
*/
public void unDoCommand() {
command.undo();
}
}
客户端调用:
public class Client {
public static void main(String[] args) {
// 创建接受者
Receiver receiver = new Receiver();
// 创建命令对象,并设置它的接受者
Command command = new ConcreteCommand(receiver);
// 创建调用者,将命令对象设置进去
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.runCommand();
invoker.unDoCommand();
}
}
输出结果:
5、智能命令
标准的命令:以上就是标准命令模式,命令的实现类没有真正地实现命令要求的功能,真正执行命令的功能的是接收者(Receiver)。
智能命令:如果命令的实现比较智能,他自己就能真实地实现命令要求的功能,而不再需要调用接收者,那这种情况就称为智能命令。
public class ConcreteCommand implements Command {
@Override
public void execute() {
System.out.println("ConcreteCommand 自己完成命令要求的功能");
}
@Override
public void undo() {
}
}
- 半智能命令:命令对象知道部分实现,其他的还需要调用接收者来完成,也就是命令的功能需要命令对象和接收者共同完成。
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
System.out.println("ConcreteCommand 完成了部分功能");
receiver.action();
}
@Override
public void undo() {
receiver.unAction();
}
}