我们将把封装带到一个全新的境界:把方法调用(method invocation)封装起来。
命令模式可将“动作的请求者” 从 “动作的执行者”中解耦。在设计中采用“命令对象”,利用命令对象,把请求(例如打开电灯)封装成一个特定的对象(例如客厅电灯对象)。所以,每个按钮都存储一个命令对象,那么当按钮被按下的时候,就可以请命令对象做相关的工作。遥控器并不知道工作内容是什么,只要有个命令对象能和正确的对象沟通,把事情做好就可以了。所以,遥控器和电灯对象解耦了。
加载调用者
1,客户创建一个命令对象。
2,客户利用setCommand()将命令对象存储在调用者中。
3,稍后。。。。客户要求调用者执行命令。请注意,就像在本章稍后会看到的:一旦命令被加载到调用者,该命令可以被使用并丢弃,或者可以被保留下来并使用多次。
命令模式的定义:
将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
现在,仔细看这个定义。我们知道一个命令对象通过在特定接受者上绑定一组动作来封装一个请求。要达到这一点,命令对象将动作和接受者包进对象中。这个对象只暴露出一个execute()方法,当次方法被调用的时候,接受者就会进行这些动作。从外面来看,其他对象不知道就近哪个接受者进行了哪些动作,只知道如果调用execute()方法,请求的目的就能达到。
一般来说,我们尽量设计“傻瓜”命令对象,它只懂得调用一个接收者的一个行为。然而,有许多“聪明”命令对象会实现许多逻辑,直接完成一个请求。当然你可以设计聪明的命令对象,只是这样一来,调用者和接收者之间的解耦程度是比不上“傻瓜”命令对象的,而且,你也不能够把接收者当做参数传给命令。
模式荣誉奖
NoCommand对象是一个空对象(null object)的例子。当你不想返回一个有意义的对象时,空对象就很有用。客户也可以将处理null的责任转移给空对象。举例来说,遥控器不可能出厂就设计了有意义的命令对象,所以提高了NoCommand对象作为代替品,当调用它的execute()方法时,这种对象什么事情都不做。
宏命令,一次可以执行多个命令。
命令模式的更多用途:队列请求
命令可以讲运算块打包(一个接收者和一组动作),然后将它传来传去,就像是一般的对象一样。现在,即使在命令对象被创建许久之后,运算依然可以被调用。事实上,它甚至可以在不同的线程中被调用。我们可以利用这样的特性衍生一些应用,例如:日程安排,线程池,工作队列等。
想象有一个工作队列,你在某一端添加命令,然后另一端是线程。线程进行下面的操作,从队列中取出一个命令,调用它的execute()方法,等待这个调用完成,然后将此命令对象丢弃,再取出下一个命令......
一个很实用的应用,菜单复用,分离了显示逻辑和业务逻辑的耦合。
命令模式的更多用途:日志请求
某些应用需要我们将所有的动作都记录在日志中,并能在系统死机之后,重新调用这些动作恢复到之前的状态。通过新增两个方法(store(),load()),命令模式就能够支持这一点。在Java中,我们可以利用对象的序列化(Serialization)实现这些方法,但是一般认为序列化最好还是只用在对象的持久化上(persistence)。
要怎么做呢?当我们执行命令的时候,将历史记录存储在磁盘中。一旦系统死机,我们就可以将命令对象重新加载,并成批次依次调用这些对象的execute()方法。
这种日志的方式对于遥控器来说没有意义,然而,有许多调用大型数据结构的动作的应用无法在每次改变发生时被快速的存储。通过使用记录日志,我们可以讲上次检查点(checkpoint)之后的所有操作记录下来,如果系统出状况,从检查点开始应用这些操作。对更高级的应用而言,这些技巧可以被扩展应用到事务处理中,也就是说,一整群操作必须全部进行完成,或者没有进行任何操作。
命令模式的以下适用环境。
1) 需要抽象出待执行的动作,然后以参数的形式提供出来——类似于过程设计中的回调机制。而命令模式正是回调机制的一个面向对象的替代品。
2) 在不同的时刻指定、排列和执行请求。一个命令对象可以有与初始请求无关的生存期。
3) 需要支持取消操作。
4) 支持修改日志功能。这样当系统崩溃时,这些修改可以被重做一遍。
5) 需要支持事务操作。
要点:
1,命令模式将发出请求的对象和执行请求的对象解耦。
2,在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作。
3,调用者通过调用命令对象的execute()发出请求,这会使得接收者的操作被调用。
4,调用者可以接受命令当做参数,甚至在运行时动态的进行。
5,命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态。
6,宏命令是命令的一中简单的延伸,允许调用多个命令。宏方法也可以支持撤销。
7,实际操作时,很常见使用“聪明”命令对象,也就是直接实现了请求,而不是将工作委托给接收者。
8,命令也可以用来实现日志和事务系统。
参考: http://www.blogjava.net/supercrsky/articles/200497.html