浅学设计模式之命令<command>模式

来源:互联网 发布:为啥淘宝无法付款 编辑:程序博客网 时间:2024/05/16 17:50

概念      

       在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象实现二者之间的松耦合。这就是命令模式(Command Pattern)


关系图:

看下命令模式是有哪些角色来组成的吧。             

  • 1)        命令角色(Command):声明执行操作的接口。有java接口或者抽象类来实现。
  • 2)        具体命令角色(Concrete Command):将一个接收者对象绑定于一个动作;调用接收者相应的操作,以实现命令角色声明的执行操作的接口。
  • 3)        客户角色(Client):创建一个具体命令对象(并可以设定它的接收者)。
  • 4)        请求者角色(Invoker):调用命令对象执行这个请求。
  • 5)        接收者角色(Receiver):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。  


   代码小例子

        物联网是未来一个卖点之一,实现物联网以后,我们可以随便遥控家里电器的情况,在这里,设计一个遥控器,具有遥控电视和洗衣机的功能。当然,你也可以添加很多遥控其他电器的功能,如果要编写这么一个类,如何更好的实现解耦呢?命令模式是个不错的选择:

首先:先建立一个Command接口:

[java] view plaincopy
  1. public interface ICommand {  
  2.     //执行  
  3.     void execute();  
  4.     //撤销  
  5.     void undo();  
  6. }  

再者,得有电视和洗衣机,才可以遥控:

[java] view plaincopy
  1. public class TV {  
  2.     public void turnOnTV(){  
  3.         System.out.println("打开电视");  
  4.     }  
  5.       
  6.     public void turnOffTV(){  
  7.         System.out.println("关闭电视");  
  8.     }  
  9.       
  10. }  

[java] view plaincopy
  1. public class Washer {  
  2.     public void turnOnWasher(){  
  3.         System.out.println("打开洗衣机");  
  4.     }  
  5.       
  6.     public void turnOffWasher(){  
  7.         System.out.println("关闭洗衣机");  
  8.     }  
  9.       
  10. }  

      实现ConcreteCommand(具体的Command):

[java] view plaincopy
  1. public class TVCommand implements ICommand {  
  2.     TV tv = null;  
  3.     public TVCommand(TV tv){  
  4.         this.tv = tv;  
  5.     }  
  6.   
  7.     @Override  
  8.     public void execute() {  
  9.         // TODO Auto-generated method stub  
  10.         tv.turnOnTV();  
  11.     }  
  12.   
  13.     @Override  
  14.     public void undo() {  
  15.         // TODO Auto-generated method stub  
  16.         tv.turnOffTV();  
  17.     }  
  18.   
  19. }  

[java] view plaincopy
  1. public class WasherCommand implements ICommand{  
  2.     Washer washer = null;  
  3.     public WasherCommand(Washer washer){  
  4.         this.washer=washer;  
  5.     }  
  6.     @Override  
  7.     public void execute() {  
  8.         // TODO Auto-generated method stub  
  9.         washer.turnOnWasher();  
  10.     }  
  11.     @Override  
  12.     public void undo() {  
  13.         // TODO Auto-generated method stub  
  14.         washer.turnOffWasher();  
  15.     }  
  16. }  

最后,实现遥控器类:

[java] view plaincopy
  1. public class RemoteControl {  
  2.     ICommand iCommand = null;  
  3.       
  4.     public void setCommand(ICommand iCommand){  
  5.         this.iCommand = iCommand;  
  6.     }  
  7.       
  8.     public void startCommand() {  
  9.         iCommand.execute();  
  10.     }  
  11.       
  12.     public void stopCommand(){  
  13.         iCommand.undo();  
  14.     }  
  15.   
  16. }  

看一下,遥控器只是把command传出去,而它丝毫不关心打开和关闭电器是如何实现的,就这样实现了解耦。

测试类:

[java] view plaincopy
  1. public class CommandTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         // TODO Auto-generated method stub  
  5.         //先得到家电  
  6.         TV tv = new TV();  
  7.         Washer washer = new Washer();  
  8.         //生成命令  
  9.         TVCommand tvCommand = new TVCommand(tv);  
  10.         WasherCommand washerCommand = new WasherCommand(washer);  
  11.           
  12.         RemoteControl remoteControl = new RemoteControl();  
  13.         //遥控器发出命令  
  14.         remoteControl.setCommand(tvCommand);  
  15.         remoteControl.startCommand();  
  16.         remoteControl.stopCommand();  
  17.         remoteControl.setCommand(washerCommand);  
  18.         remoteControl.startCommand();  
  19.         remoteControl.stopCommand();  
  20.           
  21.     }  
  22.   
  23. }  

测试结果:

打开电视
关闭电视
打开洗衣机
关闭洗衣机

想想一下,往后,如果我们在遥控器想加入遥控电风扇、空调、冰箱等等功能是不是特别清晰。


模式优点

    1.降低系统的耦合度。   

2.新的命令可以很容易地加入到系统中。   

        3.可以比较容易地设计一个组合命令。

模式缺点

    使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

适用环境

  1.系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。   

      2.系统需要在不同的时间指定请求、将请求排队和执行请求。   

      3.系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。   

      4.系统需要将一组操作组合在一起,即支持宏命令。

原创粉丝点击