设计模式学习--命令模式(Command Pattern)
2013年6月18日 设计模式学习记录
题外话:不知道同志们,怎么看待设计模式这个东西的,以小巫现在的水平,还不能把设计模式能运用到实际开发当中去,自己面向oo的设计思想还不够成熟,我知道设计模式是个好东西,只要能运用好就可以发挥很大的作用,但运用不好也会给项目带来麻烦,增加了复杂性。小巫觉得,刚学习设计模式的时候不应该有学完就能用上的思想,应该学习设计模式面对不同问题的思考模式,这才是最重要的,不同项目可能会用不同的方法去解决,不可能不变的,面对新的需求,一种方法解决不了,满足不了需求的时候,就应该选择新的方法,然而设计模式就是针对不同的情况,经过前人不断实践和总结出来的。这是小巫的见解,不知道同志们怎么看?
题外话说完,第6个设计模式:命令模式
将请求封装成对象,这可以让你使用不同的请求,队列,或者日志请求来参数化其他对象,命令模式也可以支持撤销操作。
package simpleremote; /** * 命令模式:命令接口 * @author wwj * 2013/6/10 */ public interface Command { public void execute(); }
package simpleremote; public class Light { public Light() { } public void on() { System.out.println("Light is on"); } public void off() { System.out.println("Light is off"); } }
package simpleremote; /** * 2013/6/10 * @author wwj * 实现打开灯的命令 */ public class LightOnCommand implements Command { Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } }
package simpleremote; public class GarageDoor { public GarageDoor() { } public void up() { System.out.println("Garage Door is Open"); } public void down() { System.out.println("Garage Door is Closed"); } public void stop() { System.out.println("Garage Door is Stopped"); } public void lightOn() { System.out.println("Garage light is on"); } public void lightOff() { System.out.println("Garage light is off"); } }
package simpleremote; public class GarageDoorOpenCommand implements Command { GarageDoor garageDoor; public GarageDoorOpenCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } @Override public void execute() { garageDoor.up(); } }
package simpleremote; public class SimpleRemoteControl { Command slot; public SimpleRemoteControl(){ } public void setCommand(Command command) { slot = command; } public void buttonWasPressed(){ slot.execute(); } }
package simpleremote; /** * 2013/6/10 * @author wwj * 命令模式的客户 */ public class RemoteControlTest { public static void main(String[] args) { SimpleRemoteControl remote = new SimpleRemoteControl(); Light light = new Light(); //请求的接受者 GarageDoor garageDoor = new GarageDoor(); //创建一个命令,然后将接收者传给它 LightOnCommand lightOn = new LightOnCommand(light); GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor); //把命令传给调用者 remote.setCommand(lightOn); //模拟按下按钮 remote.buttonWasPressed(); remote.setCommand(garageOpen); remote.buttonWasPressed(); } }
package remote; /** * 2013/6/10 * @author wwj * */ 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(); } }
package remote; public class LightOnCommad implements Command { Light light; public LightOnCommad(Light light) { this.light = light; } @Override public void execute() { light.on(); } }
package remote; public class LightOffCommad implements Command { Light light; public LightOffCommad(Light light) { this.light = light; } @Override public void execute() { light.off(); } }
package remote; /** * * @author wwj * 音响 */ public class Stereo { String location; public Stereo(String location) { this.location = location; } public void on() { System.out.println(location + " stereo is on"); } public void off() { System.out.println(location + " stereo is off"); } public void setCD() { System.out.println(location + " stereo is set for CD input"); } public void setDVD() { System.out.println(location + " stereo is set for DVD input"); } public void setRadio() { System.out.println(location + " stereo is set for Radio"); } public void setVolume(int volume) { // code to set the volume // valid range: 1-11 (after all 11 is better than 10, right?) System.out.println(location + " Stereo volume set to " + volume); } }
package remote; public class StereoOnWithCDCommand implements Command { Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this.stereo = stereo; } @Override public void execute() { stereo.on(); stereo.off(); stereo.setVolume(11); } }
package remote; public class StereoOffCommand implements Command { Stereo stereo; public StereoOffCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.off(); } }
package remote; /** * * @author wwj * 风扇 */ public class CeilingFan { String location = ""; int level; public static final int HIGH = 2; public static final int MEDIUM = 1; public static final int LOW = 0; public CeilingFan(String location) { this.location = location; } public void high() { // turns the ceiling fan on to high level = HIGH; System.out.println(location + " ceiling fan is on high"); } public void medium() { // turns the ceiling fan on to medium level = MEDIUM; System.out.println(location + " ceiling fan is on medium"); } public void low() { // turns the ceiling fan on to low level = LOW; System.out.println(location + " ceiling fan is on low"); } public void off() { // turns the ceiling fan off level = 0; System.out.println(location + " ceiling fan is off"); } public int getSpeed() { return level; } }
package remote; public class CeilingFanOnCommand implements Command { CeilingFan ceilingFan; public CeilingFanOnCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { ceilingFan.high(); } }
package remote; public class CeilingFanOffCommand implements Command { CeilingFan ceilingFan; public CeilingFanOffCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { ceilingFan.off(); } }
package remote; public class GarageDoorUpCommand implements Command { GarageDoor garageDoor; public GarageDoorUpCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } public void execute() { garageDoor.up(); } }
package remote; public class GarageDoorDownCommand implements Command { GarageDoor garageDoor; public GarageDoorDownCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } public void execute() { garageDoor.up(); } }
package remote; public class NoCommand implements Command { @Override public void execute() { } }
package remote; /** * 2013/6/10 * @author wwj * 逐步测试遥控器 */ 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"); //所有的灯泡命令对象 LightOnCommad livingRoomLightOn = new LightOnCommad(livingRoomLight); LightOffCommad livingRoomLightOff = new LightOffCommad(livingRoomLight); LightOnCommad kitchenLightOn = new LightOnCommad(kitchenLight); LightOffCommad kitchenLightOff = new LightOffCommad(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); //在这里,使用toString()方法,打印每个遥控器的插槽和它被指定的命令 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); } }
package undo; public class CeilingFan { public static final int HIGH = 3; public static final int MEDIUM = 2; public static final int LOW = 1; public static final int OFF = 0; String location; int speed; public CeilingFan(String location) { this.location = location; speed = OFF; } public void high() { speed = HIGH; //设置高转速 } public void medium() { speed = LOW; //设置中转速 } public void low() { speed = LOW; //设置低转速 } public void off() { speed = OFF; //关闭吊扇 } public int getSpeed() { return speed; } }
package undo; public class CeilingFanHighCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanHighCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } @Override public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.high(); } @Override public void undo() { if(prevSpeed == CeilingFan.HIGH) { ceilingFan.high(); } else if(prevSpeed == CeilingFan.MEDIUM) { ceilingFan.medium(); } else if(prevSpeed == CeilingFan.LOW) { ceilingFan.low(); } else if(prevSpeed == CeilingFan.OFF) { ceilingFan.off(); } } }
package undo; public class CeilingFanMediumCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanMediumCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.medium(); } public void undo() { if (prevSpeed == CeilingFan.HIGH) { ceilingFan.high(); } else if (prevSpeed == CeilingFan.MEDIUM) { ceilingFan.medium(); } else if (prevSpeed == CeilingFan.LOW) { ceilingFan.low(); } else if (prevSpeed == CeilingFan.OFF) { ceilingFan.off(); } } }
package undo; public class CeilingFanLowCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanLowCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.low(); } public void undo() { if (prevSpeed == CeilingFan.HIGH) { ceilingFan.high(); } else if (prevSpeed == CeilingFan.MEDIUM) { ceilingFan.medium(); } else if (prevSpeed == CeilingFan.LOW) { ceilingFan.low(); } else if (prevSpeed == CeilingFan.OFF) { ceilingFan.off(); } } }
package undo; public class Light { String location; int level; public Light(String location) { this.location = location; } public void on() { level = 100; System.out.println("Light is on"); } public void off() { level = 0; System.out.println("Light is off"); } public void dim(int level) { this.level = level; if (level == 0) { off(); } else { System.out.println("Light is dimmed to " + level + "%"); } } public int getLevel() { return level; } }
package undo; public class LightOnCommand implements Command { Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } @Override public void undo() { light.off(); } }
package undo; public class LightOffCommad implements Command { Light light; public LightOffCommad(Light light) { this.light = light; } @Override public void execute() { light.off(); } @Override public void undo() { light.on(); } }
package undo; public class NoCommand implements Command { public void execute() { } public void undo() { } }
package undo; 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]; } //当按下撤销按钮,我们调用uodoCommand实例变量的undo()方法,就可以倒转前一个命令 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(); } }
package undo; public class RemoteLoader { public static void main(String[] args) { RemoteControlWithUndo remoteControl = new RemoteControlWithUndo(); //第一组测试 Light livingRoomLight = new Light("Living Room"); LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight); LightOffCommad livingRoomLightOff = new LightOffCommad(livingRoomLight); remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff); remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0); System.out.println(remoteControl); remoteControl.undoButtonWasPushed(); remoteControl.offButtonWasPushed(0); remoteControl.onButtonWasPushed(0); System.out.println(remoteControl); remoteControl.undoButtonWasPushed(); //第二组测试 CeilingFan ceilingFan = new CeilingFan("Living Room"); CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan); CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan); CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan); remoteControl.setCommand(0, ceilingFanMedium, ceilingFanOff); remoteControl.setCommand(0, ceilingFanHigh, ceilingFanOff); remoteControl.onButtonWasPushed(0); //首先以中速开启风扇 remoteControl.offButtonWasPushed(0);//关闭 System.out.println(remoteControl); remoteControl.undoButtonWasPushed(); remoteControl.onButtonWasPushed(1); //首先以中速开启风扇 System.out.println(remoteControl); remoteControl.undoButtonWasPushed(); } }
package party; /*** * 2013/6/11 * @author wwj * 让每个遥控器都需具备“party模式” */ public class MacroCommand implements Command{ Command[] commands; //在宏命令中,用命令数组存储一大堆命令 public MacroCommand(Command[] commands) { this.commands = commands; } @Override public void execute() { for(int i = 0; i < commands.length; i++) { commands[i].execute(); } } @Override public void undo() { for(int i = 0; i < commands.length; i++) { commands[i].undo(); } } }
package party; 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); } }
------ Remote Control ------- [slot 0] party.MacroCommand party.MacroCommand [slot 1] party.NoCommand party.NoCommand [slot 2] party.NoCommand party.NoCommand [slot 3] party.NoCommand party.NoCommand [slot 4] party.NoCommand party.NoCommand [slot 5] party.NoCommand party.NoCommand [slot 6] party.NoCommand party.NoCommand [undo] party.NoCommand --- Pushing Macro On--- Light is on Living Room stereo is on Living Room TV is on Living Room TV channel is set for DVD Hottub is heating to a steaming 104 degrees Hottub is bubbling! --- Pushing Macro Off--- Light is off Living Room stereo is off Living Room TV is off Hottub is cooling to 98 degrees