目录
一、命令模式的介绍
1、定义
命令模式就是将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分隔开,这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
命令模式的角色划分:
- 命令角色(Command):该角色声明一个要给所有具体命令类的抽象接口,定义需要执行的命令。
- 具体命令角色(Concrete Command):该角色定义一个接收者和行为之间的弱耦合,实现命令方法,并调用接受者的相应操作。
- 调用者角色(Invoker Command):该角色负责调用命令对象执行请求。
- 接收者角色(Receiver):该角色负责具体实施和执行一个请求。
命令模式的UML如下:
2、使用场景
- 认为是命令的地方都可以使用命令模式。
- 系统支持命令你个的撤销/恢复、重新执行等操作的时候可以考虑使用命令模式。
- 命令的发送者和命令的执行者有不同的生命周期,不要求命令发送必须立马执行。
- 命令需要进行管理控制时。
3、优缺点
(1)优点
- 降低了系统的耦合性。新的命令可以很容易添加到系统中。
- 可以将命令组合在一起形成合成命令。
- 可以设计实现撤销、重新执行的操作。
(2)缺点
- 使用命令模式可能会导致系统中出现过多的具体命令类。
二、命令模式的实现
首先我们来看一下命令模式的执行流程:
- Client创建一个ConcreteCommand对象并指定它的Receiver对象。
- 某Invoker对象存储该ConcreteCommand对象。
- 该Invoker通过调用Command对象的Execute操作来提交一个请求。若该命令是可撤销的,ConcreteCommand就在执行Excute操作之前存储当前状态以用于取消该命令。
- ConcreteCommand对象会调用它的Receiver的一些操作以执行该请求。
场景描述:韩信带着十万大军正在征途中,突然哨骑来报,发现前方五十里有部队驻扎,是魏国旗号。于是韩信打算灭掉这支军队,他下令三万骑兵快速包围,然后让五万步兵跟进攻击。经过一个时辰的激战,这支部队终于被消灭了。则UML如下:
实现过程如下:
命令角色Command类:
/**
* 命令角色
*/
public interface Command {
/**
* 执行命令
*/
void execute();
}
具体命令角色:包围命令和攻击命令
public class SurroundCommand implements Command{
private CavalryReceiver cavalryReceiver;
public SurroundCommand(CavalryReceiver cavalryReceiver) {
this.cavalryReceiver = cavalryReceiver;
}
@Override
public void execute() {
this.cavalryReceiver.action();
}
}
public class AttackCommand implements Command{
private InfantryReceiver infantryReceiver;
public AttackCommand(InfantryReceiver infantryReceiver) {
this.infantryReceiver = infantryReceiver;
}
@Override
public void execute() {
this.infantryReceiver.action();
}
}
接收者角色:
/**
* 骑兵
*/
public class CavalryReceiver {
public void action(){
System.out.println("骑兵快速包围");
}
}
/**
* 步兵
*/
public class InfantryReceiver{
public void action() {
System.out.println("步兵跟进,聚而歼灭");
}
}
调用者角色:
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void action(){
this.command.execute();
}
}
测试类:
public class Client {
public static void main(String[] args) {
Invoker invoker = new Invoker();
Command command2 = new AttackCommand(new InfantryReceiver());
Command command1 = new SurroundCommand(new CavalryReceiver());
invoker.setCommand(command1);
invoker.action();
System.out.println("============");
invoker.setCommand(command2);
invoker.action();
}
}