1:PDF上传链接
【免费】敏捷软件开发(原则模式与实践)资源-CSDN文库
没有人天生就具有命令他人的权利。
--Denis Diderot(1713一1784,法国哲学家,百料全书编者)
在近几年记述过的所有设计模式中,我认为COMMAND模式是最简单、最优雅的模式之一。
但是我们将会看到,这种简单性是带有欺骗性的。COMMAND模式的适用范围是非常宽广的。
如图13.1所示,COMMAND模式简单得几乎可笑。程序13.1中的代码并没有起到削弱这种印象的作用。该模式仅由一个具有惟一方法的接口组成,这似乎是荒谬的。
图13.1COMMAND模式
程序13.1 Command.java
public interface Command
{
public void do();
}
但是,事实上,该模式横过了一条非常有趣的界线。而这个交界处正是所有有趣的复杂性之所在。大多数类都是一组方法和相应的一组变量的结合。COMMAND模式不是这样的。它只是封装了一个没有任何变量的函数。
从严格的面向对象意义上来讲,这种做法是被强烈反对的一因为它具有功能分解的味道。它把函数层面的任务提升到了类的层面。这简直是对面向对象的亵渎!然而,在这两个思维范式(paradigm)的碰撞处,有趣的事情发生了。
13.1:简单的COMMAND
图13.2 复印机软件中一些简单的Command
这些类的职责很明显。如果调用RelayOnCommand的do0方法,它就会开启一些继电器。如果调用MotorOffCommand的do0方法,它就会关闭一些发动机。继电器或者发动机的地址作为构造函数的参数传到对象中去。
有了这种结构,我们就可以在系统中传递Command对象并调用它们的do0方法,而无需明确地知道它们所代表的Command的种类。这会带来一些有趣的简化。
13.4:ACTIVE OBJECT模式
ACTIVE OBJECT模式是我最喜欢使用COMMAND模式的地方之一。这是实现多线程控制的一项古老的技术。该模式有多种使用方式,为许多工业系统提供了一个简单的多任务核心。
想法很简单。考虑程序13.2和程序13.3。ActiveObjectEngine对象维护了一个Command对象的链表。用户可以向该引擎(engine)增加新的命令,或者调用runO。unO函数只是遍历链表,执行并去除每个命令。
程序13.2 Active0 bjectEngine.java
import java.util.LinkedList;
import java.util.Iterator;
public class ActiveobjectEngine
{
LinkedList itsCommands = new LinkedList ()
public void addCommand (Command c)
{
itsCommands.add (c);
}
public void run ()
{
while (!itsCommands.isEmpty ()
{
Command c (Command)itsCommands.getFirst ()
itsCommands.removeFirst ()
c.execute();
}
}
}
程序13,3 Command.java
public interface Command
{
public void execute() throws Exception;
}
这似乎没有给人太深刻的印象。但是想象一下如果链表中的一个Command对象会克隆自己并把克隆对象放到链表的尾部,会发生什么呢?这个链表永远不会为空,run()函数永远不会返回。
13.5:结论
COMMAND模式的简单性掩盖了它的多功能性。COMMAND模式可以应用于多种不同的美妙用途,范围涉及数据库事务操作、设备控制、多线程核心以及GUI的do/undo管理。
有人认为COMMAND模式不符合面向对象的思维范式(paradigm),因为它对函数的关注超过了类。这也许是真的,但是在实际的软件开发中,COM①MAND模式是非常有用的。