命令模式是对命令的封装,命令模式把发出命令的责任和执行命令的责任分开,委派给不同的对象。也就是调用命令的对象和执行命令的对象分开独立地演化,他们之间通过某种相对较弱的耦合联系在一起。
命令模式具有以下特点:
(1) 命令模式使新的命令很容易地被加入到系统
(2) 允许接收请求的一方---命令执行者 是否要否决命令
(3) 能较容易地设计一个命令队列
(4) 可以容易的实现对请求的Undo 和 Redo
(5) 在需要的情况下可以将命令记录到日志
这样说比较抽象,其UML示意图如下:
将Reciever 作为参数构造具体命令 PrintCommand 和AddCommand,并在他们的 execution() 方法中“通知”Reciever 执行命令--调用 doCommand 方法,这样命令接收者可以决定是否执行以及如何执行命令。并且可以方便的加入新的具体命令,如 RemoveCommand, updateCommand等等。以如下方式调用命令:
Command pcommand = new PrintCommand(new Reciever());
Invoker invoker = new Invoker(pcommand);
invoker.invoke();
如果需要实现 Undo Redo 功能,可以扩展一个新的命令比如 UndoRedoCommand.java, 实现Command 接口并提供undo redo 方法,这个命令需要保存前一次命令调用时系统的状态信息,比如命令执行者(Reciever)的状态,方法调用时的参数等,情况比较复杂。如果要支持多层的undo Redo, 系统还要存储曾经被调用过的命令清单以及命令执行者的状态信息。清单允许的最大长度就是Undo Redo 的层数。
命令模式的使用场景:
a. 需要在不同的时间指定请求,将请求排队。一个命令对象和原先的请求发出者(Invoker)可以有不同的生命周期,即使原先的命令请求者已经不存在了,命令对象本身仍可以是活动的。此时命令的接收者可以在本地,也可以在网络上的其他地方。命令对象序列化后传给远端接收者.
b. 系统需要支持Undo or Redo.
c. 系统需要保存命令执行记录.
d. 系统需要支持事务,需要回滚.
命令模式的初衷就是把请求(命令)封装,使得对请求的操作与请求的发出者隔离。当然,命令本身也可以成为请求的具体执行者,这时命令的接收者角色是不需要的,这样的设计使得命令本身比较“沉重”。通常命令是作为请求者和接收者之间实现弱耦合的纽带。
--------------------------------------------------------------------
完整sample code 见附件
--------------------------------------------------------------------