遥控器案例,控制灯开或关,音响音量大小,设置CD
1、把命令封装成接口,不同设备继承接口实现功能;
如上图,灯的开、关和音响开、关、调音量、设置CD功能类定义好,其相应功能的执行命令封装成接口,Control通过命令接口的方法实现对应功能;
public class Light { String loc="";//灯位置,如卧室,客厅 public Light(String loc){ this.loc=loc; } public void on(){ System.out.println(loc+" On"); } public void off(){ System.out.println(loc+" Off"); } }
public class Stereo { static int volume=0; public void on(){ System.out.println("Stereo On"); } public void off(){ System.out.println("Stereo Off"); } public void setCD(){ System.out.println("Stereo setCD"); } public void setVol(int vol){ this.volume=vol; System.out.println("Stereo volume="+volume); } public int getVol(){ return volume; } public void start(){ System.out.println("Stereo Start"); } }
public interface Command { public void execute(); public void undo(); }
单独的功能,如灯的开、关和音响的开、关、调大音量、调小音量,实现命令接口
public class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } public void execute() { light.on(); } public void undo() { light.off(); } }
public class LightOffCommand implements Command { private Light light; public LightOffCommand(Light light) { this.light = light; } public void execute() { light.off(); } public void undo() { light.on(); } }
public class StereoOnCommand implements Command { private Stereo stereo; public StereoOnCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { //可以多个命令同时执行 stereo.on(); stereo.setCD(); } public void undo() { stereo.off(); } }
public class StereoOffCommand implements Command { private Stereo stereo; public StereoOffCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.off(); } public void undo() { stereo.on(); } }
public class StereoAddVolCommand implements Command { private Stereo stereo; public StereoAddVolCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { int vol = stereo.getVol(); if (vol < 11) { stereo.setVol(++vol); } } public void undo() { int vol = stereo.getVol(); if (vol > 0) { stereo.setVol(--vol); } } }
public class StereoSubVolCommand implements Command { private Stereo stereo; public StereoSubVolCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { int vol = stereo.getVol(); if (vol > 0) { stereo.setVol(--vol); } } public void undo() { int vol = stereo.getVol(); if (vol < 11) { stereo.setVol(++vol); } } }
NoCommand类,用来初始化命令控制器上按钮,内部实现命令接口,但不执行功能,就类似按按钮不起作用
public class NoCommand implements Command { public void execute() { } public void undo() { } }
遥控器接口,遥控器通过控制每一排的开、关按钮来让相应的功能命令执行
public interface Control { //slot位置,即打开或关闭哪排按钮 void onButton(int slot); void offButton(int slot); void undoButton(); void setCommand(int slot, Command onCommand, Command offCommand); }
public class CommandModeControl implements Control { private Command[] onCommands; private Command[] offCommands; private Stack<Command> stack=new Stack<Command>(); public CommandModeControl() { onCommands = new Command[5]; offCommands = new Command[5]; Command noCommand = new NoCommand(); for (int i = 0; i < onCommands.length; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; } } public void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } public void onButton(int slot) { onCommands[slot].execute(); stack.push(onCommands[slot]); } public void offButton(int slot) { offCommands[slot].execute(); stack.push(offCommands[slot]); } public void undoButton() { stack.pop().undo(); } }
下面再添加一同时控制多个功能的命令
public class MarcoCommand implements Command { private Command[] commands; public MarcoCommand(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(); } } }
遥控器操作设备,也就是Control中的onButton、offButton调用Command的execute方法,undoButton执行Command的undo方法
设备功能实现Command接口,各自实现不同,而Command接口对外暴露的只有相同的方法
public class ControlTest { public static void main(String[] args){ Control control=new CommandModeControl(); Light bedroomLight=new Light("BedRoom"); Light kitchLight=new Light("Kitch"); Stereo stereo=new Stereo(); Command bedroomLightOn=new LightOnCommand(bedroomLight); Command bedroomLightOff=new LightOffCommand(bedroomLight); Command kitchLightOn=new LightOnCommand(kitchLight); Command kitchLightOff=new LightOffCommand(kitchLight); //同时开、关两个灯 Command[] onCommands={bedroomLightOn,kitchLightOn}; Command[] offCommands={bedroomLightOff,kitchLightOff}; Command marcoCommandOn=new MarcoCommand(onCommands); Command marcoCommandOff=new MarcoCommand(offCommands); Command stereoOn=new StereoOnCommand(stereo); Command stereoOff=new StereoOffCommand(stereo); Command stereoAddVol=new StereoAddVolCommand(stereo); Command stereoSubVol=new StereoSubVolCommand(stereo); control.setCommand(0,bedroomLightOn,bedroomLightOff); control.setCommand(1,kitchLightOn,kitchLightOff); control.setCommand(2,stereoOn,stereoOff); control.setCommand(3,stereoAddVol,stereoSubVol); control.setCommand(4,marcoCommandOn,marcoCommandOff); control.onButton(0); control.offButton(0); control.onButton(1); control.offButton(1); control.onButton(2); control.offButton(2); control.onButton(3); control.offButton(3); System.out.println("~~~~~~~~~~~~~"); control.onButton(4); control.offButton(4); } }
解耦后,设备升级或添加新设备,都不会影响其他设备代码