1.定义
命令模式(Command)将一个请求封装为一个对象,从而使可用不同的请求对客户进行参数化,对请求排队或请求记录日志,以及支持可撤销的操作。
2.结构
2.1 UML类图
2.2 角色
- Command :声明执行命令的接口,拥有执行命令的抽象方法 execute()。
- Concrete Command :命令具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
- Receiver:需要被调用的目标对象,是具体命令对象业务的真正实现者。
- Invoker:是请求的发送者,它通常拥有多个命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
3.实现
interface Command {
void execute();
}
class AttackCommand implements Command {
private Soldier soldier;
public AttackCommand(Soldier soldier) {
this.soldier = soldier;
}
@Override
public void execute() {
soldier.action();
System.out.println("进攻了!");
}
}
class RetreatCommand implements Command {
private Soldier soldier;
public RetreatCommand(Soldier soldier) {
this.soldier = soldier;
}
@Override
public void execute() {
soldier.action();
System.out.println("撤退了!");
}
}
/**
* 士兵:命令接收者(Receiver)
*/
class Soldier {
private String name;
public Soldier(String name) {
this.name = name;
}
public void action() {
System.out.println("士兵 " + name + " 开始执行命令......");
}
}
/**
* 将军:命令调用者(Invoker)
*/
class General {
private List<Command> commandList = new ArrayList<>();
public void addCommands(Command command){
this.commandList.add(command);
}
/**
* 发送执行所有任务的指令
*/
public void sendCommands(){
for(Command command : commandList){
command.execute();
}
}
}
/**
* 测试类
*/
public class CommandDemo {
public static void main(String[] args) {
Soldier soldier = new Soldier("许三多");
General general = new General();
general.addCommands(new AttackCommand(soldier));
general.addCommands(new RetreatCommand(soldier));
general.sendCommands();
}
}
4.总结
4.1 优点
- 降低耦合度,较容易的设计一个命令队列。
- 允许接收请求的一方决定是否要否决请求。
- 容易实现对请求的撤销和重做。
- 增加新的具体命令类很容易,因为加进新的具体命令类不影响其他的类。
- 把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
4.2 缺点
- 会产生过多具体命令类.。
4.3 应用场景
- 对象之间的调用:创建目标对象实例,设置调用参数,调用目标对象的方法,有时需要使用一个专门的类对调用过程加以封装,该类就称为command类,便于功能的再利用。
- 整个调用过程比较复杂或存在多处调用。
- 调用前后需要对调用参数进行某些处理
- 调用前后需要进行某些额外处理,例如:日志、缓存、记录历史操作等。
本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文!