命令(Command)模式

系统 2034 0
命令(Command)模式 :又称Action模式或者Transaction模式。它属于对象的行为模式。命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和撤销功能。
GoF命令模式结构图如下:
命令(Command)模式
 
 
 命令模式是有以下角色:
抽象命令(Command)角色 :声明执行操作的接口。
具体命令(ConcreteCommand)角色 :将一个接收者对象绑定到一个动作上。调用接收者相应的操作,以实现Execute方法。
客户端(Client)角色 :创建一个命令对象并设定它的接收者。
请求者(Invoker)角色 :负责调用命令对象的执行请求;
接收者(Receiver)角色 :负责具体实施和执行一个请求相关的操作。任何一个类都可以作为一个接收者。
上面模型的模拟代码如下:
Java代码   收藏代码
  1. package  command;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午7:39:48  
  6.  *描述:接收者角色  
  7.  */   
  8. public   class  Receiver {  
  9.   
  10.      public  Receiver() {  
  11.          super ();  
  12.     }  
  13.   
  14.      /**  
  15.      *   
  16.      *作者:alaric  
  17.      *时间:2013-8-20下午7:40:00  
  18.      *描述:行动方法  
  19.      */   
  20.      public   void  action(){  
  21.         System.out.println( "接收者接到命令,开始行动" );  
  22.     }  
  23. }  
 
Java代码   收藏代码
  1. package  command;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午7:36:51  
  6.  *描述:抽象命令角色  
  7.  */   
  8. public   interface  Command {  
  9.   
  10.      /**  
  11.      *   
  12.      *作者:alaric  
  13.      *时间:2013-8-20下午7:36:40  
  14.      *描述:执行方法  
  15.      */   
  16.      public   void  execute();  
  17. }  
 
Java代码   收藏代码
  1. package  command;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午7:37:10  
  6.  *描述:具体命令角色  
  7.  */   
  8. public   class  ConcreteCommand  implements  Command {  
  9.   
  10.      private  Receiver receiver;  
  11.       
  12.       
  13.      public  ConcreteCommand(Receiver receiver) {  
  14.          super ();  
  15.          this .receiver = receiver;  
  16.     }  
  17.   
  18.   
  19.      @Override   
  20.      public   void  execute() {  
  21.           
  22.         receiver.action();  
  23.           
  24.     }  
  25.       
  26.   
  27. }  
 
Java代码   收藏代码
  1. package  command;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午7:41:07  
  6.  *描述:  
  7.  */   
  8. public   class  Invoker {  
  9.   
  10.      private  Command command;  
  11.   
  12.      public  Invoker(Command command) {  
  13.          super ();  
  14.          this .command = command;  
  15.     }  
  16.       
  17.      public   void  action(){  
  18.         command.execute();  
  19.     }  
  20. }  
 
Java代码   收藏代码
  1. package  command;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午7:33:51  
  6.  *描述:客户端角色  
  7.  */   
  8. public   class  Client {  
  9.   
  10.      /**  
  11.      *作者:alaric  
  12.      *时间:2013-8-20下午7:33:44  
  13.      *描述:  
  14.      */   
  15.      public   static   void  main(String[] args) {  
  16.         Receiver receiver =  new  Receiver();  
  17.         Command command =  new  ConcreteCommand(receiver);  
  18.         Invoker invoker =  new  Invoker(command);  
  19.         invoker.action();  
  20.     }  
  21.   
  22. }  
 命令模式是对命令的封装,它把发出命令的责任和执行命令的责任分隔开,委派给不同的对象。每一个命令都是一个操作,请求的一方发出请求要求执行一个操作;接收的一方收到请求并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方接口,更不必知道请求是怎么被接收,以及操作是否被执行,何时被执行,以及是怎么被执行的。命令允许请求方和接收方各自都能独立演化,从而具有以下优点:
1、命令模式使新的命令在不改变现有结构代码的情况下很容易被加入到系统里;
2、允许接收请求的一方决定是否否决请求;
3、能较容易地设计一个命令队列;
4、可以容易地实现对请求的Undo和Redo操作;
5、在需要的情况下以较容易地将命令记入日志。
 
在讲门面模式的时候曾经提过一个例子,我们小时玩过投币的那种游戏机,一个方向操作杆,四个动作按钮,在一个操作面板上,封装了复杂的逻辑在机器内部,提供简单的操作界面,是一个门面的例子,然而每个操作发出一个命令,来控制游戏人物的运动和各种动作。方向操作杆是一个移动的命令,传入移动的方向和距离作为参数,还有出拳按键发出出拳命令,脚踢按键发出脚踢的命令,那还有组合操作命令,比如下踢腿(操作杆向下和踢脚按钮按下)。现在我们用命令模式来模拟这个场景。类的模型图如下:

命令(Command)模式
 如上图所示:Client相当于小时候的我们,Control相关于控制执行器,我们可以控制踢(KickCommand)、打(FistCommand)、移动(MoveCommand),这些命令的最终实现者也是接收者是游戏机(GameMachine)。
代码如下:
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-21上午7:15:53  
  6.  *描述:接收者  
  7.  */   
  8. public   class  GameMachine {  
  9.   
  10.      public   void  fist() {  
  11.         System.out.println( "出拳" );  
  12.     }  
  13.       
  14.      public   void  kick() {  
  15.         System.out.println( "出脚" );  
  16.     }  
  17.       
  18.      public   void  move(String direction){  
  19.         System.out.println( "向" +direction+ "移动" );  
  20.     }  
  21.   
  22. }  
 
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午10:20:35  
  6.  *描述:命令接口  
  7.  */   
  8. public   interface  Command {  
  9.   
  10.      //执行方法   
  11.      public   void  execute();  
  12.       
  13.      //这里还可以加入撤销方法,回滚方法等   
  14. }  
 
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-21上午7:17:02  
  6.  *描述:拳打  
  7.  */   
  8. public   class  FistCommand  implements  Command {  
  9.      private  GameMachine machine;  
  10.       
  11.       
  12.       
  13.      public  FistCommand(GameMachine machine) {  
  14.          super ();  
  15.          this .machine = machine;  
  16.     }  
  17.   
  18.   
  19.   
  20.      @Override   
  21.      public   void  execute() {  
  22.         machine.fist();  
  23.     }  
  24.   
  25.   
  26. }  
 
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-21上午7:42:21  
  6.  *描述:脚踢命令  
  7.  */   
  8. public   class  KickCommand  implements  Command {  
  9.      private  GameMachine machine;  
  10.       
  11.      public  KickCommand(GameMachine machine) {  
  12.          super ();  
  13.          this .machine = machine;  
  14.     }  
  15.   
  16.      @Override   
  17.      public   void  execute() {  
  18.         machine.kick();  
  19.     }  
  20.   
  21. }  
 
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-21上午7:17:02  
  6.  *描述:移动命令  
  7.  */   
  8. public   class  MoveCommand  implements  Command {  
  9.      private  GameMachine machine;  
  10.      private  String direction;  
  11.       
  12.       
  13.      public  MoveCommand(GameMachine machine,String direction) {  
  14.          super ();  
  15.          this .machine = machine;  
  16.          this .direction = direction;  
  17.     }  
  18.   
  19.   
  20.   
  21.      @Override   
  22.      public   void  execute() {  
  23.         machine.move(direction);  
  24.     }  
  25.   
  26.       
  27.   
  28. }  
 
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-21上午7:43:14  
  6.  *描述:控制类  
  7.  */   
  8. public   class  Control {  
  9.       
  10.      private  Command fistCommand;  
  11.      private  Command kickCommand;  
  12.      private  Command moveCommand;  
  13.       
  14.      public  Control(Command fistCommand, Command kickCommand, Command moveCommand) {  
  15.          super ();  
  16.          this .fistCommand = fistCommand;  
  17.          this .kickCommand = kickCommand;  
  18.          this .moveCommand = moveCommand;  
  19.     }  
  20.       
  21.      public   void  fist(){  
  22.         fistCommand.execute();  
  23.     }  
  24.       
  25.      public   void  kick(){  
  26.         kickCommand.execute();  
  27.     }  
  28.       
  29.      public   void  move(){  
  30.         moveCommand.execute();  
  31.     }  
  32.   
  33. }  
 
Java代码   收藏代码
  1. package  command.example;  
  2. /**  
  3.  *   
  4.  *作者:alaric  
  5.  *时间:2013-8-20下午9:26:42  
  6.  *描述:客户端角色  
  7.  */   
  8. public   class  Client {  
  9.   
  10.      /**  
  11.      *作者:alaric  
  12.      *时间:2013-8-20下午9:26:36  
  13.      *描述:测试  
  14.      */   
  15.      public   static   void  main(String[] args) {  
  16.   
  17.         GameMachine machine =  new  GameMachine();  
  18.         Command fistCommand =  new  FistCommand(machine);  
  19.         Command kickCommand =  new  KickCommand(machine);  
  20.         Command moveCommand =  new  MoveCommand(machine,  "左" );  
  21.           
  22.         Control control =  new  Control(fistCommand, kickCommand, moveCommand);  
  23.         control.fist();  
  24.         control.kick();  
  25.         control.move();  
  26.           
  27.          //其实在不同命令模式的情况下就是下面这样直接调用,   
  28.          //就会让调用者和实际命令执行者紧紧耦合在一起,还有一个好处   
  29.          //就是可以在   
  30.          //machine.fist();   
  31.          //machine.kick();   
  32.          //machine.move("左");   
  33.     }  
  34.   
  35. }  

 运行结果如下:

出拳

出脚

向左移动

 
通过上面代码可以看出,本来客户端可以直接调用接收者来执行动作的,现在在中间引入了命令,这些命令由调用者(Invoker这里是Control)来调用,从而对客户端和命令接收者解耦了,增加了命令后,使得命令除了execute方法外,可以插入很多其它动作,比如redo,undo,或者记录日志等。

命令(Command)模式


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论