用于将请求发送者与接收者进行解耦
命令模式的定义
将一个请求封装成一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作模式或事务模式。
其UML类图如下所示
命令模式的关键在于引入了命令类。请求发送者只需要指定一个命令对象,再通过命令对象来调用请求接收者的处理方法。
在命令模式结构图中包含以下四个角色:
(1)Command(抽象命令类):抽象类或者接口,在其中声明了用于执行请求的execute()等方法,这些方法可以调用请求接收者的相关操作。
(2) ConcreteCommand(具体命令类):对抽象命令类的实现
(3)Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。
(4)Receiver(接收者):接收者执行与请求相关的操作,它具体实现对请求的业务处理
其典型的抽象命令代码如下:
abstract class Command{
public abstract void execute();
}
class Invoker{
private Command command;
public Invoker(Command command){
this.command = command;
}
public vodi setCommand(Command command){
this.command = command;
}
public void call(){
command.execute();
}
}
class ConcreteCommand extends Command{
private Receiver receiver = new Receiver(); //维持一个请求接收者对象的引用
public void execute(){
receiver.action(); //调用请求接收者的业务处理方法action()
}
}
class Receiver{
public void action(){
//具体操作
}
}
命令模式的本质是对请求进行封装。一个请求对应于一个命令,将发出命令的责任和执行命令的责任分隔开。
命令队列的的实现
有时候当一个请求发送了需要不止一个请求接收者来产生响应,这些请求接收者将逐个执行业务方法,完成对请求的处理,此时可以通过命令队列的方式来进行实现。
新增一个CommandQueue类来实现命令队列
class CommandQueue{
//定义一个ArrayList来存储命令队列
private ArrayList<Command> commands= new ArrayList<Command>();
public void addCommand(Command command){
commands.add(command);
}
public void removeCommand(Command command){
commands.remove(command);
}
public void execute(){
for(Object command: commands){
((Command)command).execute();
}
}
}
当新增了一个命令队列后 请求发送者Invoker也发生了改变
class Invoker{
private CommandQueue commandQueue; //维持一个CommandQueue对象引用
public Invoker(CommandQueue commandQueue){
this.commandQueue = commandQueue;
}
//set注入在此省略
public void call(){
commandQueue.execute();
}
}
命令模式总结
命令模式的优点
(1)降低系统的耦合度
(2) 新的命令可以很容易的加入系统中
(3) 可以比较容易的设计一个命令队列或者组合命令
(4) 为请求的撤销和恢复操作提供了一种设计和实现方案
命令模式的缺点
使用命令模式可能会导致某些系统中有过多的命令类。
适用场景
(1)系统需要将请求的发送者和请求接收者进行解耦
(2)系统需要支持命令的撤销和恢复操作
(3)系统需要将一组操作组合