命令模式
命令模式的封装性非常好,把请求方(Invoker)和执行方(Receiver)分开,扩展性也非常好。
定义
将一个请求封装成一个对象,从而使得不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

实现
Receiver
抽象接收者,定义每个接收者都必须完成的业务。
| 12
 3
 
 | public abstract class Receiver{public abstract void doSomething();
 }
 
 | 
具体的Receiver
| 12
 3
 4
 5
 6
 7
 
 | public class Concrete1Reveiver extends Receiver{public void doSomething(){}
 }
 
 public class Concrete2Reveiver extends Receiver{
 public void doSomething(){}
 }
 
 | 
Command
不同的命令实现都需要继承该类,实现自己的execute逻辑。
| 12
 3
 
 | public abstract class Command{public abstract  void execute();
 }
 
 | 
具体的命令实现类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | public class ConcreteCommand1 extends Command{private Receiver receiver;
 public ConcreteCommand1(Receiver receiver){
 this.receiver = receiver;
 }
 public void execute(){
 this.receiver.doSomething();
 }
 }
 
 public class ConcreteCommand2 extends Command{
 private Receiver receiver;
 public ConcreteCommand2(Receiver receiver){
 this.receiver = receiver;
 }
 public void execute(){
 this.receiver.doSomething();
 }
 }
 
 | 
Invoker
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | public class Invoker{private Command command;
 public void setCommand(Command command){
 this.command = command;
 }
 public void action(){
 this.command.execute();
 }
 }
 
 | 
Use
| 12
 3
 
 | Invoker invoker = new Invoker();invoker.setCommand(new ConcreteCommand1(new Concrete1Reveiver()));
 invoker.action();
 
 | 
模式应用
优点
- 解耦
 调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需要调用Command抽象类的execute方法即可,不需要了解是哪个接收者执行。
- 可扩展性好
 Command子类可以非常容易的扩展,调用者Invoker和高层的模块Client不产生严重的代码耦合。
- 与其他模式混合使用
 与责任链模式结合,实现命令族解析任务
 与模版方法结合,减少Command子类膨胀的问题。
缺点
Command的子类会随着命令的增多逐步膨胀。
命令的撤销
反命令
通过相反的命令来实现命令的撤销。
结合备忘录模式
结合备忘录模式还原最后状态,折中发昂发适合接收者为状态的变更情况,而不适合事件处理。
代码实例
假设有个录音机,录音机面板有三个按钮, play, rewind, stop。
需要根据三个按钮作出相应的反馈。
Receiver
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | public class AudioPlayer {
 public void paly(){
 System.out.println("Play");
 }
 
 public void rewind(){
 System.out.println("Rewind");
 }
 
 public void stop(){
 System.out.println("Stop");
 }
 }
 
 | 
Command
不同的Command调用不同的Receiver命令。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | public abstract class Command {
 protected static AudioPlayer audioPlayer = new AudioPlayer();
 
 public abstract void execute();
 
 }
 
 public class PlayCommand extends Command {
 @Override
 public void execute() {
 super.audioPlayer.paly();
 }
 }
 
 public class RewindCommand extends Command {
 @Override
 public void execute() {
 audioPlayer.rewind();
 }
 }
 
 public class StopCommand extends Command {
 @Override
 public void execute() {
 audioPlayer.stop();
 }
 }
 
 | 
Invoker
用于转发Command
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | public class KeyPad {private Command command;
 
 public void setCommand(Command command) {
 this.command = command;
 }
 
 public void action() {
 this.command.execute();
 }
 }
 
 | 
Use
| 12
 3
 4
 5
 6
 7
 
 | KeyPad keyPad = new KeyPad();
 keyPad.setCommand(new RewindCommand());
 keyPad.action();
 
 keyPad.setCommand(new StopCommand());
 keyPad.action();
 
 | 
如果后期需要增加一个按钮,stopAndRewind(),直接增加一个Command子类即可,其他地方不需要动。
| 12
 3
 4
 5
 6
 7
 8
 
 | public class StopAndRewindCommand extends  Command {
 @Override
 public void execute() {
 audioPlayer.stop();
 audioPlayer.rewind();
 }
 }
 
 |