2005年2月16日星期三

《ASD》设计模式:Command和Active Object

Command模式:
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. - 《Design Patterns》

Command模式的关键在于只包含一个 Execute方法,子类在实现这个接口时,在Execute方法中,完成特定的任务。可以说,这是一个非常简单的模式。
《ASD》中提到了该模式的三种用法:
1. Invoker可以和任意一个Command挂钩,而且不需要了解这到底是个什么ConcreteCommand,然后在需要的时候调用这个Command对象的Execute方法就行了。这在消息驱动的的系统中非常常见,每个trigger就是一个invoker。那么如何把Command和invoker挂钩呢?方法很多,最cool的方法是在系统外用一个配置文件来指定。这样不需要重新编译就可以改变软件运行的方式。可以参考Source Insight的界面。Source Insight中可以任意配置菜单项和工具栏按钮。其实现应该就是应用了这种Command模式。
2.上面的方法是否让人想起了Template模式?有点相像吧。顺着这个思路去想,就可以把Command模式应用于Transaction。让一个类来解决Transaction的init和uninit问题,中间包含一个Command的队列。这样就可以把这个队列中的全部command当作一个transaction了。这样的作法可以把Transaction的实现和逻辑分离开来,是很漂亮的实现。同样的思路,也可以用在类似的问题上,需要init和uninit,中间有不定量的操作。
3.如果真的用来解决transaction问题,那么就必须具备roll back的能力。然而这个很容易实现,只要在command类中,添加undo方法就可以了。剩下的活交给invoker来处理。
4.此外还有一个附带的好处。command类和一个单独的execute方法其实很相似,但是command类的对象有生命周期,可以由程序来控制。因此,一个command对象,可以在提交了很长时间以后再批量执行。
除了这些以外,《Design Pattern》还提到了Command模式的其他使用方法。虽然这些方法未必使用,但我还是把它们列在这里:
1.command对象和command对象的序列都可以serialization。这样如果软件被有意或无意的中止(例如crash),在重新启动后,还可以接续之前没有完成的任务。
2.Command模式如果和Composite模式接合,就可以作出MacroCommand。^_^,这个idea虽然很cool,但是可以用到的地方大概不多吧。

Active Object模式不属于《Design Pattern》23模式。实际上,她是一种特殊的Command Queue。其特殊之处在于:
1. 队列的拥有者会顺序地执行队列中所有Command对象的Execute方法。(这个其实不算特殊)
2.Command对象在自己的Execute方法结束前,可以把一个新的command对象(实际上常常是这个command对象自己)再加到队列的尾部。
看出来了吗,这个队列有可能不会终止的,他可以一直执行下去。这个可以作为一个应用或者服务的主模块了,想像一下她可以作多少事情吧。
《ASD》指出这个模式可以用来在一个线程中处理多任务的问题!!! ^_^ 太cool了。
如何处理呢?你可以把每个command对象看作是一个任务。他在Execute函数中,处理自己的任务,在任务告一段落时,记录自己的状态,然后把自己插入到队列的尾部,结束Execute方法。当队列轮完一周后,又会再次执行这个command对象的Execute方法。 ^_^ 很cool吧。
那么这种方法和多线程的方法相比有什么有缺点呢?
最大的优点是,所有的command都在同一个线程中,因此切换时,不需要进入内核模式!!超高效啊!!而且,可以有很多很多的command,数量上远远超过多线程的数量。
缺点嘛,是这种方法需要用户自己来实现调度,另外这其实是一种非剥夺模式的多任务,如果command处理不好,就会连累其它所有的command,因此实际上比多线程要更复杂。(嘿嘿,程序员能够怕麻烦吗?)
还有一点,Active Object运行于单线程,也就是说,她不能享受多处理器或多处理器核心带来的性能上的改善。
其实,这最后一点是非常致命的一点。也就是说,在当前intel的超线程CPU机器上,如果系统的负担并不重的时候。Active Object的效率有可能比多线程更低。
Anyway,这是一个非常有趣的模式。只是一般的程序员可能没有机会用到。但是请记住她,也许能有那么一次机会,可一用她来爽上一把。

没有评论: