命令模式(command pattern)
命令模式,实现了把命令调用与命令执行分开。用途广泛。
它可以批量执行命令,比如它可以用于进度条的显示。多个命令顺序执行,进度
条来表示命令的执行进度。如果每个命令都用command封装,成为命令对象
(command object),并且每个命令对象都有获取执行时间的方法,那么就可以方
便的获取整个执行过程的时间。据此就可以用进度条显示出这一系列任务的执行
进度。它可以实现重做(undo)操作。数据库事物中的rollback处理。GUI程序使用
命令模式更为常见,从中,你甚至可以看到MVC架构的缩影。
命令模式的用法多种多样,但总离不开三个角色和一个对象: 调用者、接受者、
客户端,和命令对象(command object). 调用者决定命令执行的时机,即它是命
令的发起者;它不知道命令的执行细节,只管发起。接受者是真正执行命令的对
象。命令对象是实现命令接口的对象,命令对象往往封装或引用了接收者。实际
编程中也不必拘泥于形式,命令对象和接收者也可合二为一,即这个对象既实现
了命令接口,又亲自执行了命令细节。客户端负责初始化调用者、接收者、命令
对象以及提供必要的信息(参数),一旦初始化完毕,各个对象的联系通路也就
建立起来了。
下面,我举一个经典的例子来说明调用者、接收者、客户端和命令对象的关系。
这个例子中要调用两个命令,我还会在后面给出调用一个命令的情况。
(代码来自维基)
/*the Invoker class*/public class Switch { private Command flipUpCommand; private Command flipDownCommand; public Switch(Command flipUpCmd, Command flipDownCmd) { this.flipUpCommand = flipUpCmd; this.flipDownCommand = flipDownCmd; } public void flipUp() { flipUpCommand.execute(); } public void flipDown() { flipDownCommand.execute(); }} /*Receiver class*/public class Light { public Light() { } public void turnOn() { System.out.println("The light is on"); } public void turnOff() { System.out.println("The light is off"); }} /*the Command interface*/public interface Command { void execute();} /*the Command for turning on the light*/public class FlipUpCommand implements Command { private Light theLight; public FlipUpCommand(Light light) { this.theLight=light; } public void execute(){ theLight.turnOn(); }} /*the Command for turning off the light*/public class FlipDownCommand implements Command { private Light theLight; public FlipDownCommand(Light light) { this.theLight=light; } public void execute() { theLight.turnOff(); }} /*The test class or client*/public class PressSwitch { public static void main(String[] args) { Light lamp = new Light(); Command switchUp = new FlipUpCommand(lamp); Command switchDown = new FlipDownCommand(lamp); Switch s = new Switch(switchUp,switchDown); try { if (args[0].equalsIgnoreCase("ON")) { s.flipUp(); } else if (args[0].equalsIgnoreCase("OFF")) { s.flipDown(); } else { System.out.println("Argument "ON" or "OFF" is required."); } } catch (Exception e){ System.out.println("Arguments required."); } }}
if (args[0].equalsIgnoreCase("ON")) { lamp.turnOn();}if (args[0].equalsIgnoreCase("OFF")) { lamp.turnOff();}
package pattern;//TestTransactionCommand.javaimport java.util.*;final class CommandReceiver {private int[] c;private CommandArgument a;private CommandReceiver() {c = new int[2];}private static CommandReceiver cr = new CommandReceiver();public static CommandReceiver getHandle() {return cr;}public void setCommandArgument(CommandArgument a) {this.a = a;}public void methAdd() {c = a.getArguments();System.out.println("The result is " + (c[0] + c[1]));}public void methSubtract() {c = a.getArguments();System.out.println("The result is " + (c[0] - c[1]));}}interface Command{public void execute();}class CommandManager {private Command myCommand;public CommandManager(Command myCommand) {this.myCommand = myCommand;}public void runCommands() {myCommand.execute();}}class TransactionCommand implements Command {private CommandReceiver commandreceiver;private Vector commandnamelist, commandargumentlist;private String commandname;private CommandArgument commandargument;private Command command;public TransactionCommand() {this(null, null);}public TransactionCommand(Vector commandnamelist, Vector commandargumentlist) {this.commandnamelist = commandnamelist;this.commandargumentlist = commandargumentlist;commandreceiver = CommandReceiver.getHandle();}public void execute() {for (int i = 0; i < commandnamelist.size(); i++) {commandname = (String) (commandnamelist.get(i));commandargument = (CommandArgument) ((commandargumentlist.get(i)));commandreceiver.setCommandArgument(commandargument);String classname = "pattern."+commandname + "Command";try {Class cls = Class.forName(classname);command = (Command) cls.newInstance();} catch (Throwable e) {System.err.println(e);}command.execute();}}}class AddCommand extends TransactionCommand {private CommandReceiver cr;public AddCommand() {cr = CommandReceiver.getHandle();}public void execute() {cr.methAdd();}}class SubtractCommand extends TransactionCommand {private CommandReceiver cr;public SubtractCommand() {cr = CommandReceiver.getHandle();}public void execute() {cr.methSubtract();}}class CommandArgument {private int[] args;CommandArgument() {args = new int[2];}public int[] getArguments() {return args;}public void setArgument(int i1, int i2) {args[0] = i1;args[1] = i2;}}public class TestTransactionCommand {private Vector clist, alist;public TestTransactionCommand() {clist = new Vector();alist = new Vector();}public void clearBuffer(Vector c, Vector a) {clist.removeAll(c);alist.removeAll(a);}public Vector getClist() {return clist;}public Vector getAlist() {return alist;}public static void main(String[] args) {CommandArgument ca, ca2;TestTransactionCommand t = new TestTransactionCommand();ca = new CommandArgument();ca.setArgument(2, 8);Vector myclist = t.getClist();Vector myalist = t.getAlist();myclist.addElement("Add");myalist.addElement(ca);TransactionCommand tc = new TransactionCommand(myclist, myalist);CommandManager cm = new CommandManager(tc);cm.runCommands();t.clearBuffer(myclist, myalist);ca2 = new CommandArgument();ca2.setArgument(5, 7);myclist = t.getClist();myalist = t.getAlist();myclist.addElement("Subtract");myalist.addElement(ca2);myclist.addElement("Add");myalist.addElement(ca2);TransactionCommand tc2 = new TransactionCommand(myclist, myalist);CommandManager cm2 = new CommandManager(tc2);cm2.runCommands();}}