设计模式读书笔记-命令模式

来源:岁月联盟 编辑:exp 时间:2011-07-21

命令模式,将请求封装成对象,这可以让你使用不同的请求/队列/或日志请求来参数化对象,命令模式也可以支持撤销操作. 当发出请求和执行请求的对象需要解耦时,使用命令对象.
我们来看一个例子:遥控器例子,我们想通过遥控器控制家中的各种电器;实现这样的功
能要求:.
  1 各种电器提供控制命令接口;
  2 遥控器对象
  3 遥控器上各个插槽对应的命令,命令对象,
  4 各种电器
定义命令接口:
public interface Command {
       public void execute();
}
各种电器对象,我们将各种电器对象单独定义并将对象命令封装进来.也就是各种电器对象的命令方法;
public class Light {
       public Light() {
       }
       public void on() {
              System.out.println("Light is on");
       }
       public void off() {
              System.out.println("Light is off");
       }
}
定义各种电器各种命令的对象实现COMMAND的接口;对应遥控器的各个操作;
public class LightOnCommand implements Command {
       Light light;
      public LightOnCommand(Light light) {
              this.light = light;
       }
      public void execute() {
              light.on();
       }
}
public class LightOffCommand implements Command {
       Light light;
      public LightOffCommand(Light light) {
              this.light = light;
       }
      public void execute() {
              light.off();
       }
}
定义遥控器对象;
public class SimpleRemoteControl {
       Command slot;
      public SimpleRemoteControl() {}
      public void setCommand(Command command) {
              slot = command;
       }
      public void buttonWasPressed() {
              slot.execute();
       }
}
下面实现一个简单的测试类:
public class RemoteControlTest {
       public static void main(String[] args) {
              SimpleRemoteControl remote = new SimpleRemoteControl();
              Light light = new Light();
              LightOnCommand lightOn = new LightOnCommand(light);
              remote.setCommand(lightOn);
              remote.buttonWasPressed();
        remote.setCommand(lightOff);
              remote.buttonWasPressed();
 
    }
}
遥控器不需要命令到底是如何执行的,只需要在调用的时候调用就可以;命令都是动态传入的。实现了请求者和执行者的完全解耦,通过命令接口把两部分连接起来。
 
空对象应用:
public class NoCommand implements Command {
       public void execute() { }
}
在初始化命令时,比如遥控器中可能某个插槽无对应命令,我们可以为空,返回空对象;这个对象什么都不做,这种方式被常用,也可以作为设计模式的一种。
 
我们重新实现遥控器(有些电器对象代码这里没给出,可以去51CTO下载。
 
public class RemoteControl {
       Command[] onCommands;
       Command[] offCommands;
 
       public RemoteControl() {
              onCommands = new Command[7];
              offCommands = new Command[7];
 
              Command noCommand = new NoCommand();
              for (int i = 0; i < 7; i++) {
                     onCommands[i] = noCommand;
                     offCommands[i] = noCommand;
              }
       }
 
       public void setCommand(int slot, Command onCommand, Command offCommand) {
              onCommands[slot] = onCommand;
              offCommands[slot] = offCommand;
       }
 
       public void onButtonWasPushed(int slot) {
              onCommands[slot].execute();
       }
 
       public void offButtonWasPushed(int slot) {
              offCommands[slot].execute();
       }
 
       public String toString() {
              StringBuffer stringBuff = new StringBuffer();
              stringBuff.append("/n------ Remote Control -------/n");
              for (int i = 0; i < onCommands.length; i++) {
                     stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
                            + "    " + offCommands[i].getClass().getName() + "/n");
              }
              return stringBuff.toString();
       }
}
 
测试类:
public class RemoteLoader {
 
       public static void main(String[] args) {
              RemoteControl remoteControl = new RemoteControl();
 
              Light livingRoomLight = new Light("Living Room");
              Light kitchenLight = new Light("Kitchen");
              CeilingFan ceilingFan= new CeilingFan("Living Room");
              GarageDoor garageDoor = new GarageDoor("");
              Stereo stereo = new Stereo("Living Room");
 
              LightOnCommand livingRoomLightOn =
                            new LightOnCommand(livingRoomLight);
              LightOffCommand livingRoomLightOff =
                            new LightOffCommand(livingRoomLight);
              LightOnCommand kitchenLightOn =
                            new LightOnCommand(kitchenLight);
              LightOffCommand kitchenLightOff =
                            new LightOffCommand(kitchenLight);
 
              CeilingFanOnCommand ceilingFanOn =
                            new CeilingFanOnCommand(ceilingFan);
              CeilingFanOffCommand ceilingFanOff =
                            new CeilingFanOffCommand(ceilingFan);
 
              GarageDoorUpCommand garageDoorUp =
                            new GarageDoorUpCommand(garageDoor);
              GarageDoorDownCommand garageDoorDown =
                            new GarageDoorDownCommand(garageDoor);
 
              StereoOnWithCDCommand stereoOnWithCD =
                            new StereoOnWithCDCommand(stereo);
              StereoOffCommand  stereoOff =
                            new StereoOffCommand(stereo);
 
              remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
              remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff);
              remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff);
              remoteControl.setCommand(3, stereoOnWithCD, stereoOff);
 
              System.out.println(remoteControl);
 
              remoteControl.onButtonWasPushed(0);
              remoteControl.offButtonWasPushed(0);
              remoteControl.onButtonWasPushed(1);
              remoteControl.offButtonWasPushed(1);
              remoteControl.onButtonWasPushed(2);
              remoteControl.offButtonWasPushed(2);
              remoteControl.onButtonWasPushed(3);
              remoteControl.offButtonWasPushed(3);
       }
}
 
命令模式具有撤销机制:
public interface Command {
       public void execute();
       public void undo();
}
命令接口增加撤销方法;
ublic class LightOffCommand implements Command {
       Light light;
 
       public LightOffCommand(Light light) {
              this.light = light;
       }
 
       public void execute() {
              light.off();
       }
 
       public void undo() {
              light.on();
       }
相应的电器命令实现撤销命令;
遥控器类增加记录撤销命令的属性;
public class RemoteControlWithUndo {
       Command[] onCommands;
       Command[] offCommands;
       Command undoCommand;
 
       public RemoteControlWithUndo() {
              onCommands = new Command[7];
              offCommands = new Command[7];
 
              Command noCommand = new NoCommand();
              for(int i=0;i<7;i++) {
                     onCommands[i] = noCommand;
                     offCommands[i] = noCommand;
              }
              undoCommand = noCommand;
       }
 
       public void setCommand(int slot, Command onCommand, Command offCommand) {
              onCommands[slot] = onCommand;
              offCommands[slot] = offCommand;
       }
 
       public void onButtonWasPushed(int slot) {
              onCommands[slot].execute();
              undoCommand = onCommands[slot];
       }
 
       public void offButtonWasPushed(int slot) {
              offCommands[slot].execute();
              undoCommand = offCommands[slot];
       }
 
       public void undoButtonWasPushed() {
              undoCommand.undo();
       }
 
       public String toString() {
              StringBuffer stringBuff = new StringBuffer();
              stringBuff.append("/n------ Remote Control -------/n");
              for (int i = 0; i < onCommands.length; i++) {
                     stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
                            + "    " + offCommands[i].getClass().getName() + "/n");
              }
              stringBuff.append("[undo] " + undoCommand.getClass().getName() + "/n");
              return stringBuff.toString();
       }
}
 
此外,也可以定义宏命令,一次执行一组命令;与事务机制相似;
public class MacroCommand implements Command {
       Command[] commands;
 
       public MacroCommand(Command[] commands) {
              this.commands = commands;
       }
      public void execute() {
              for (int i = 0; i < commands.length; i++) {
                     commands[i].execute();
              }
       }
      public void undo() {
              for (int i = 0; i < commands.length; i++) {
                     commands[i].undo();
              }
       }
}
这时实现一个简单定义宏;
在测试中实现如下:
public class RemoteLoader {
 
       public static void main(String[] args) {
 
              RemoteControl remoteControl = new RemoteControl();
 
              Light light = new Light("Living Room");
              TV tv = new TV("Living Room");
              Stereo stereo = new Stereo("Living Room");
              Hottub hottub = new Hottub();
 
              LightOnCommand lightOn = new LightOnCommand(light);
              StereoOnCommand stereoOn = new StereoOnCommand(stereo);
              TVOnCommand tvOn = new TVOnCommand(tv);
              HottubOnCommand hottubOn = new HottubOnCommand(hottub);
              LightOffCommand lightOff = new LightOffCommand(light);
              StereoOffCommand stereoOff = new StereoOffCommand(stereo);
              TVOffCommand tvOff = new TVOffCommand(tv);
              HottubOffCommand hottubOff = new HottubOffCommand(hottub);
 
              Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};
              Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};
 
              MacroCommand partyOnMacro = new MacroCommand(partyOn);
              MacroCommand partyOffMacro = new MacroCommand(partyOff);
 
              remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
 
              System.out.println(remoteControl);
              System.out.println("--- Pushing Macro On---");
              remoteControl.onButtonWasPushed(0);
              System.out.println("--- Pushing Macro Off---");
              remoteControl.offButtonWasPushed(0);
       }
}
调用者可以通过调用命令对象的EXCUTE()方法调用命令;
本文出自 “清风” 博客