[Head First设计模式笔记]----命令模式
命令模式定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
类图:
适用设计方案举例:实现一种遥控器,该遥控器具有七个可编程的插槽(每个都可以指定到一个不同的家电装置),每个插槽都有对应的开关按钮。这个遥控器还具备一个整体的撤销按钮。另外,多家厂商已经开发了一组Java类,例如电灯、风扇、热水器、音响设备和其他类似的可控制装置。遥控器如下图所示:
实现Code:
(1) 如下设备相关的Java类由厂商提供:
1 //CeilingFan.java 2 package RemoteControl.device; 3 4 public class CeilingFan { 5 String name; 6 public CeilingFan(String str) 7 { 8 name = str; 9 } 10 11 public void on() 12 { 13 System.out.println(name + "CeilingFan On"); 14 } 15 16 public void off() 17 { 18 System.out.println(name + "CeilingFan Off"); 19 } 20 }
1 //GarageDoor.java 2 package RemoteControl.device; 3 4 public class GarageDoor { 5 String name; 6 public GarageDoor(String str) 7 { 8 name = str; 9 } 10 11 public void up() 12 { 13 System.out.println(name + "GarageDoor On"); 14 } 15 16 public void down() 17 { 18 System.out.println(name + "GarageDoor Off"); 19 } 20 }
1 //Light.java 2 package RemoteControl.device; 3 4 public class Light { 5 String name; 6 public Light(String str) 7 { 8 name = str; 9 } 10 11 public void on() 12 { 13 System.out.println(name + "Light On"); 14 } 15 16 public void off() 17 { 18 System.out.println(name + "Light Off"); 19 } 20 }
1 //Stereo.java 2 package RemoteControl.device; 3 4 public class Stereo { 5 String name; 6 public Stereo(String str) 7 { 8 name = str; 9 } 10 11 public void on() 12 { 13 System.out.println(name + "Stereo On"); 14 } 15 16 public void off() 17 { 18 System.out.println(name + "Stereo Off"); 19 } 20 21 public void setCD() 22 { 23 System.out.println(name + "Stereo setCD"); 24 } 25 26 public void setVolume(int num) 27 { 28 System.out.println(name + "Stereo setVolume:" + num); 29 } 30 }
(2) 将厂商提供的设备Java类库(即receiver)封装到Command类里面:
1 //CeilingFanOffCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.CeilingFan; 5 6 public class CeilingFanOffCommand implements Command{ 7 CeilingFan cf; 8 9 public CeilingFanOffCommand(CeilingFan cf) 10 { 11 this.cf = cf; 12 } 13 14 @Override 15 public void execute() 16 { 17 cf.off(); 18 } 19 20 @Override 21 public void undo() { 22 cf.on(); 23 } 24 25 }
1 //CeilingFanOnCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.CeilingFan; 5 6 7 public class CeilingFanOnCommand implements Command{ 8 CeilingFan cf; 9 10 public CeilingFanOnCommand(CeilingFan cf) 11 { 12 this.cf = cf; 13 } 14 15 @Override 16 public void execute() 17 { 18 cf.on(); 19 } 20 21 @Override 22 public void undo() { 23 cf.off(); 24 } 25 }
1 //Command.java 2 package RemoteControl.Command; 3 4 public interface Command { 5 public void execute(); 6 public void undo(); 7 }
1 //GarageDoorDownCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.GarageDoor; 5 6 public class GarageDoorDownCommand implements Command { 7 GarageDoor gd; 8 9 public GarageDoorDownCommand(GarageDoor gd) 10 { 11 this.gd = gd; 12 } 13 14 @Override 15 public void execute() 16 { 17 gd.down(); 18 } 19 20 @Override 21 public void undo() { 22 gd.up(); 23 } 24 }
1 //GarageDoorUpCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.GarageDoor; 5 6 public class GarageDoorUpCommand implements Command { 7 GarageDoor gd; 8 9 public GarageDoorUpCommand(GarageDoor gd) 10 { 11 this.gd = gd; 12 } 13 14 @Override 15 public void execute() 16 { 17 gd.up(); 18 } 19 20 @Override 21 public void undo() { 22 gd.down(); 23 } 24 }
1 //LightOffCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.Light; 5 6 public class LightOffCommand implements Command { 7 Light light; 8 9 public LightOffCommand(Light light) 10 { 11 this.light = light; 12 } 13 14 @Override 15 public void execute() 16 { 17 light.off(); 18 } 19 20 @Override 21 public void undo() { 22 light.on(); 23 } 24 }
1 //LightOnCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.Light; 5 6 public class LightOnCommand implements Command { 7 8 Light light; 9 10 public LightOnCommand(Light light) 11 { 12 this.light = light; 13 } 14 15 @Override 16 public void execute() 17 { 18 light.on(); 19 } 20 21 @Override 22 public void undo() { 23 light.off(); 24 } 25 }
1 //NoCommand.java 2 package RemoteControl.Command; 3 4 public class NoCommand implements Command{ 5 public void execute() 6 {} 7 8 public void undo() 9 {} 10 }
1 //StereoOffCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.Stereo; 5 6 public class StereoOffCommand implements Command { 7 Stereo stereo; 8 9 public StereoOffCommand(Stereo stereo) 10 { 11 this.stereo = stereo; 12 } 13 14 public void execute() 15 { 16 stereo.off(); 17 } 18 19 @Override 20 public void undo() { 21 stereo.on(); 22 } 23 }
1 //StereoOnWithCDCommand.java 2 package RemoteControl.Command; 3 4 import RemoteControl.device.Stereo; 5 6 public class StereoOnWithCDCommand implements Command { 7 Stereo stereo; 8 9 public StereoOnWithCDCommand(Stereo stereo) 10 { 11 this.stereo = stereo; 12 } 13 14 public void execute() 15 { 16 stereo.on(); 17 stereo.setCD(); 18 stereo.setVolume(11); 19 } 20 21 @Override 22 public void undo() { 23 stereo.off(); 24 } 25 }
(3) 实现Invoker类:
1 //RemoteControl.java 2 package RemoteControl; 3 4 import RemoteControl.Command.Command; 5 import RemoteControl.Command.NoCommand; 6 7 public class RemoteControl { 8 Command[] onCommands; 9 Command[] offCommands; 10 Command undoCommand; 11 12 public RemoteControl(){ 13 onCommands = new Command[7]; 14 offCommands = new Command[7]; 15 16 Command noCommand = new NoCommand(); 17 for(int i=0; i<7; i++) 18 { 19 onCommands[i] = noCommand; 20 offCommands[i] = noCommand; 21 } 22 undoCommand = noCommand; 23 } 24 25 public void setCommand(int slot, Command onCommand, Command offCommand) 26 { 27 onCommands[slot] = onCommand; 28 offCommands[slot] = offCommand; 29 } 30 31 public void onButtonWasPushed(int slot) 32 { 33 onCommands[slot].execute(); 34 undoCommand = onCommands[slot]; 35 } 36 37 public void offButtonWasPushed(int slot) 38 { 39 offCommands[slot].execute(); 40 undoCommand = offCommands[slot]; 41 } 42 43 public void undoButtonWasPushed() 44 { 45 undoCommand.undo(); 46 } 47 48 public String toString() 49 { 50 StringBuffer stringBuff = new StringBuffer(); 51 stringBuff.append("\n-------- Remote Control --------\n"); 52 for(int i = 0; i < onCommands.length; i++) 53 { 54 stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() 55 + " " + offCommands[i].getClass().getName() + "\n"); 56 } 57 return stringBuff.toString(); 58 } 59 60 }
1 //RemoteControlTest.java 2 package RemoteControl; 3 4 import RemoteControl.Command.CeilingFanOffCommand; 5 import RemoteControl.Command.CeilingFanOnCommand; 6 import RemoteControl.Command.GarageDoorDownCommand; 7 import RemoteControl.Command.GarageDoorUpCommand; 8 import RemoteControl.Command.LightOffCommand; 9 import RemoteControl.Command.LightOnCommand; 10 import RemoteControl.Command.StereoOffCommand; 11 import RemoteControl.Command.StereoOnWithCDCommand; 12 import RemoteControl.device.CeilingFan; 13 import RemoteControl.device.GarageDoor; 14 import RemoteControl.device.Light; 15 import RemoteControl.device.Stereo; 16 17 public class RemoteControlTest { 18 public static void main(String[] args) 19 { 20 RemoteControl remoteControl = new RemoteControl(); 21 22 Light livingRoomLight = new Light("Living Room"); 23 Light kitchenLight = new Light("Kitchen"); 24 CeilingFan ceilingFan = new CeilingFan("Living Room"); 25 GarageDoor garageDoor = new GarageDoor(""); 26 Stereo stereo = new Stereo("Living Room"); 27 28 LightOnCommand lightRoomLightOn = new LightOnCommand(livingRoomLight); 29 LightOffCommand lightRoomLightOff = new LightOffCommand(livingRoomLight); 30 31 LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight); 32 LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight); 33 34 CeilingFanOnCommand ceilingFanOn = new CeilingFanOnCommand(ceilingFan); 35 CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan); 36 37 GarageDoorUpCommand garageDoorUp = new GarageDoorUpCommand(garageDoor); 38 GarageDoorDownCommand garageDoorDown = new GarageDoorDownCommand(garageDoor); 39 40 StereoOnWithCDCommand stereoOnWithCD = new StereoOnWithCDCommand(stereo); 41 StereoOffCommand stereoOff = new StereoOffCommand(stereo); 42 43 remoteControl.setCommand(0, lightRoomLightOn, lightRoomLightOff); 44 remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff); 45 remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff); 46 remoteControl.setCommand(3, garageDoorUp, garageDoorDown); 47 48 System.out.println(remoteControl); 49 50 remoteControl.onButtonWasPushed(0); 51 remoteControl.offButtonWasPushed(0); 52 remoteControl.onButtonWasPushed(1); 53 remoteControl.offButtonWasPushed(1); 54 remoteControl.onButtonWasPushed(2); 55 remoteControl.offButtonWasPushed(2); 56 remoteControl.onButtonWasPushed(3); 57 remoteControl.offButtonWasPushed(3); 58 remoteControl.undoButtonWasPushed(); 59 } 60 }
实现类图: