命令模式(别名:动作,事务)
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
在许多设计中,经常涉及到一个对象请求另一个对象调用其方法到达某种目的。如果请求者不希望或无法直接和被请求者打交道,即不希望或无法含有被请求者的引用,那么就可以使用命令模式。
模式的结构中包括四种角色:
-
接收者(Receiver)
-
命令(Command)接口
-
具体命令(ConcreteCommand)
-
请求者(Invoker)
接收者(Receiver)
1.接收者(Receiver) : CompanyArmy.java
public class CompanyArmy{
public void sneakAttack(){
System.out.println("我们知道如何偷袭敌人,保证完成任务");
}
}
命令(Command)接口
2.命令(Command)接口 : Command.java
public interface Command {
public abstract void execute();
}
具体命令(ConcreteCommand)
public class ConcreteCommand implements Command{
CompanyArmy army; //含有接收者的引用
ConcreteCommand(CompanyArmy army){
this.army=army;
}
public void execute(){ //封装着指挥官的请求
army.sneakAttack(); //偷袭敌人
}
}
请求者(Invoker)
4.请求者(Invoker) ArmySuperior.java
public class ArmySuperior{
Command command; //用来存放具体命令的引用
public void setCommand(Command command){
this.command=command;
}
public void startExecuteCommand(){
//让具体命令执行execute()方法
command.execute();
}
}
5.应用 Application.java
public class Application{
public static void main(String args[]){
CompanyArmy 三连=new CompanyArmy();
Command command=new ConcreteCommand(三连);
ArmySuperior 指挥官=new ArmySuperior();
指挥官.setCommand(command);
指挥官.startExecuteCommand();
}
}
在命令模式中,请求者(Invoker)不直接与接收者(Receiver)交互,即请求者(Invoker)不包含接收者(Receiver)的引用,因此彻底消除了彼此之间的耦合。
命令模式满足“开-闭原则”。如果增加新的具体命令和该命令的接受者,不必修改调用者的代码,调用者就可以使用新的命令对象;反之,如果增加新的调用者,不必修改现有的具体命令和接受者,新增加的调用者就可以使用已有的具体命令。
由于请求者的请求被封装到了具体命令中,那么就可以将具体命令保存到持久化的媒介中,在需要的时候,重新执行这个具体命令。因此,使用命令模式可以记录日志。
使用命令模式可以对请求者的“请求”进行排队。每个请求都各自对应一个具体命令,因此可以按一定顺序执行这些具体命令。