1、设计模式 -Command(命令 )模式GoF:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数华;对请求排队或记录请求日志,以及支持克撤销的操作。在网上查找 Command 模式的相关资料,大多都是关于用户界面的。可能和GOF 的先入为主有关系。在 GoF 的书中,四位作者举了个文本编辑器的例子。Command 模式通过将请求本身变成一个对象来使工具箱对象可向未指定的应用对象提出请求。这个对象可被存储并像其他对象一样被传递。记得以前在设计模式精解的读书笔记中学习了几条经验,其中一条是:注意封装变化点。在 Command 模式中就是对变化点的典型封装。在 Command 模式中有
2、一个关键的抽象类,一般人们命名为 Command 类。他定义了一个执行操作的接口。它有一个抽象的 execute 操作。具体的 Command 子类(继承自 Command 的具体类)将接收者(Receiver 类)作为其一个事例变量,并实现 execute 操作,指定接收者采取的动作。而接收者有执行该请求所需要的具体信息。下面举个例子:先定义关键的 Command 抽象类(这里也可以用接口):package Command;public abstract class Commandprotected Receiver receiver; public Command(Receiver rec
3、eiver) this.receiver = receiver; /end Command(.)abstract public void execute();/end abstract class Command再继承一个具体类:package Command;public class ConcreteCommand extends Commandpublic ConcreteCommand( Receiver receiver )super(receiver);/end ConcreteCommand(.)public void execute() receiver.action(); /e
4、nd execute()/end class ConcreteCommand定义一个 Receiver 类:package Command;public class Receiverpublic void action() System.out.println(“Receiver.Action()“);/end Action()/end class Receiver定义一个 Invoker 类:package Command;class Invoker private Command command; public void setCommand( Command command ) mand
5、 = command; /end setCommand(.)public void executeCommand() command.execute(); /end executeCommand()/end class Invoker最后是调用:package Command;public class CommandPatternReceiver rceiver = new Receiver(); Command command = new ConcreteCommand(rceiver); Invoker invoker = new Invoker();/* Creates a new in
6、stance of CommandPattern */public CommandPattern()/end CommandPatternpublic void showCommandPattern()invoker.setCommand(command);invoker.executeCommand();/end showCommandPattern()public static void main(String args)System.out.println(“-“);System.out.println(“The Command Pattern!“);CommandPattern cp
7、= new CommandPattern();cp.showCommandPattern();System.out.println(“-“);/end main(.)/end class CommandPattern下面给出 UML 图,看一下他们之间的关系:关于 Command 模式的知识在 GoF 的书里还介绍了好多,在我所做过的项目中一直也没有用到过 Command 模式所以在这里也就不多说了,详细的还是参考GOF 的书吧。设计模式之 Command板桥里人 http:/ 2002/4/23/(转载请保留)模式实战书籍Java 实用系统开发指南 Command 模式是最让我疑惑的一个模式
8、 ,我在阅读了很多代码后, 才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command 模式实际上不是个很具体,规定很多的模式, 正是这个灵活性,让人有些 confuse.Command 定义n 将来自客户端的请求传入一个对象,无需了解这个请求激活的 动作或有关接受这个请求的处理细节。这是一种两台机器之间通讯联系性质的模式,类似传统过程语 言的 CallBack 功能。 优点:解耦了发送者和接受者之间联系。 发送者调用一个操作,接受者接受请求执行相应的动作,因为使用 Command 模式解耦,发送者无需知道接受者任何接口。不少 Comma
9、nd 模式的代码都是针对图形界面的 ,它实际就是菜单命令, 我们在一个下拉菜单选择一个命令时,然后会执行一些动作.将这些命令封装成在一个类中,然后用户( 调用者)再对这个类进行操作 ,这就是 Command 模式,换句话说,本来用户( 调用者)是直接调用这些命令的,如菜单上打开文档 (调用者),就直接指向打开文档的代码,使用 Command 模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了.显然这样做的好处是符合封装的特性,降低耦合度,Command 是将对行为进行封装的典型模式,Factory 是将创建进行封装的模式,从 Command 模式,我也
10、发现设计模式一个“通病“:好象喜欢将简单的问题复杂化 , 喜欢在不同类中增加第三者,当然这样做有利于代码的健壮性 可维护性 还有复用性.如何使用?具体的 Command 模式代码各式各样 ,因为如何封装命令,不同系统 ,有不同的做法.下面事例是将命令封装在一个 Collection 的 List 中,任何对象一旦加入 List 中,实际上装入了一个封闭的黑盒中, 对象的特性消失了,只有取出时,才有可能模糊的分辨出:典型的 Command 模式需要有一个接口 .接口中有一个统一的方法, 这就是“将命令/请求封装为对象“:public interface Command public abstra
11、ct void execute ( );具体不同命令/请求代码是实现接口 Command,下面有三个具体命令public class Engineer implements Command public void execute( ) /do Engineers command public class Programmer implements Command public void execute( ) /do programmers commandpublic class Politician implements Command public void execute( ) /do P
12、oliticians command按照通常做法,我们就可以直接调用这三个 Command,但是使用 Command 模式,我们要将他们封装起来,扔到黑盒子 List 里去:public class producerpublic static List produceRequests() List queue = new ArrayList();queue.add( new DomesticEngineer() );queue.add( new Politician() );queue.add( new Programmer() );return queue; 这三个命令进入 List 中后,
13、已经失去了其外表特征,以后再取出,也可能无法分辨出谁是 Engineer 谁是 Programmer 了,看下面客户端如何调用 Command 模式:public class TestCommand public static void main(String args) List queue = Producer.produceRequests();for (Iterator it = queue.iterator(); it.hasNext(); )/客户端直接调用 execute 方法,无需知道被调用者的其它更多类的方法名。(Command)it.next().execute(); 由此
14、可见,调用者基本只和接口打交道, 不合具体实现交互,这也体现了一个原则 ,面向接口编程,这样,以后增加第四个具体命令时,就不必修改调用者 TestCommand 中的代码了.理解了上面的代码的核心原理,在使用中, 就应该各人有自己方法了, 特别是在如何分离调用者和具体命令上,有很多实现方法,上面的代码是使用“从 List 过一遍“的做法.这种做法只是为了演示.使用 Command 模式的一个好理由还因为它能实现 Undo 功能 .每个具体命令都可以记住它刚刚执行的动作,并且在需要时恢复.Command 模式在界面设计中应用广泛 .Java 的 Swing 中菜单命令都是使用 Command 模式,由于 Java 在界面设计的性能上还有欠缺,因此界面设计具体代码我们就不讨论 ,网络上有很多这样的示例.参考: