命令模式
2015-06-14 20:30
197 查看
一.很吊的前言
这些绝密的文件投递箱已经促成了间谍工业的革命。我只需要把需求丢进去,就会有人消失,政府一夜之间改朝换代,而我的干洗衣服也洗好了。我不必管它们是何时,何地,如何完成的,反正就是完成了。二.简单的命令模式实例
现在智能硬件这么火,我想设计一个可以遥控床头灯的遥控器,可以实现灯的开或者关在这个设计里面,涉及到哪些类呢,有床头灯,有遥控器,遥控器怎么打开灯呢,我首先的想法如下:1.在遥控器中有一个Light的成员变量light
2.new出遥控器实例的时候就对light赋一个Light的实例
3.在遥控器的open和close中调用light的open和close
以上的设计有什么缺点:
遥控器无法扩展了,如果我想控制空调怎么办,想设计一个牛逼的遥控器,这种设计显然是失败的。
那怎么办,这样改进呢:
在代码中添加一个空调的引用,这样就可以将遥控器设置为空调的遥控器了,可是下次我要控制风扇怎么办,难道一只要更改遥控器的代码么,显然不行。
终极的办法来了,命令模式初显身手:
将各种命令也设计为一个类,开灯,关灯,开空调,关空调都是我们可以扩展的类,而遥控器的按钮我们可以setCommond,将各种命令类的实例赋给遥控器中的Commond超类实例。
看代码,很简单的,首先是命令的接口:
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"); } }
开灯关灯的命令类:
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(); } }
遥控器类,用setCommond,实现了扩展:
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(); } }
三.完整的家用多功能遥控器
上面的例子其实只是针对遥控器的某一个按钮实现了功能,可以开或者关,下面来实现一个完成的家用多功能遥控器,可以控制风扇,门,灯,热浴盆,CD唱片机。家用电器类以及对应的命令类:
//灯 public class Light { String location = ""; public Light(String location) { this.location = location; } public void on() { System.out.println(location + " light is on"); } public void off() { System.out.println(location + " light is off"); } } //灯对应的命令 public class LightOffCommand implements Command { Light light; public LightOffCommand(Light light) { this.light = light; } public void execute() { light.off(); } } public class LightOnCommand implements Command { Light light; public LightOnCommand(Light light) { this.light = light; } public void execute() { light.on(); } } public class LivingroomLightOffCommand implements Command { Light light; public LivingroomLightOffCommand(Light light) { this.light = light; } public void execute() { light.off(); } } public class LivingroomLightOnCommand implements Command { Light light; public LivingroomLightOnCommand(Light light) { this.light = light; } public void execute() { light.on(); } } //CD唱片机 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); } } //CD唱片机对应命令 public class StereoOnWithCDCommand implements Command { Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.on(); stereo.setCD(); stereo.setVolume(11); } } public class StereoOffCommand implements Command { Stereo stereo; public StereoOffCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.off(); } } //风扇 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; } } //风扇的命令 public class CeilingFanOffCommand implements Command { CeilingFan ceilingFan; public CeilingFanOffCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { ceilingFan.off(); } } public class CeilingFanOnCommand implements Command { CeilingFan ceilingFan; public CeilingFanOnCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { ceilingFan.high(); } } //门 public class GarageDoor { String location; public GarageDoor(String location) { this.location = location; } public void up() { System.out.println(location + " garage Door is Up"); } public void down() { System.out.println(location + " garage Door is Down"); } public void stop() { System.out.println(location + " garage Door is Stopped"); } public void lightOn() { System.out.println(location + " garage light is on"); } public void lightOff() { System.out.println(location + " garage light is off"); } } //门的命令 public class GarageDoorDownCommand implements Command { GarageDoor garageDoor; public GarageDoorDownCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } public void execute() { garageDoor.up(); } } public class GarageDoorUpCommand implements Command { GarageDoor garageDoor; public GarageDoorUpCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } public void execute() { garageDoor.up(); } } //热浴盆 public class Hottub { boolean on; int temperature; public Hottub() { } public void on() { on = true; } public void off() { on = false; } public void bubblesOn() { if (on) { System.out.println("Hottub is bubbling!"); } } public void bubblesOff() { if (on) { System.out.println("Hottub is not bubbling"); } } public void jetsOn() { if (on) { System.out.println("Hottub jets are on"); } } public void jetsOff() { if (on) { System.out.println("Hottub jets are off"); } } public void setTemperature(int temperature) { this.temperature = temperature; } public void heat() { temperature = 105; System.out.println("Hottub is heating to a steaming 105 degrees"); } public void cool() { temperature = 98; System.out.println("Hottub is cooling to 98 degrees"); } } //热浴盆的命令 public class HottubOffCommand implements Command { Hottub hottub; public HottubOffCommand(Hottub hottub) { this.hottub = hottub; } public void execute() { hottub.cool(); hottub.off(); } } public class HottubOnCommand implements Command { Hottub hottub; public HottubOnCommand(Hottub hottub) { this.hottub = hottub; } public void execute() { hottub.on(); hottub.heat(); hottub.bubblesOn(); } }
遥控器,一共有14个按钮,7个开,7个关:
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(); } }
上面每个按钮的初始化时,都初始化为NoCommand,它什么都不做:
public class NoCommand implements Command { public void execute() { } }
下面是测试函数:
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 class LightOnCommand implements Command { Light light; public LightOnCommand(Light light) { this.light = light; } public void execute() { light.on(); } public void undo() { light.off(); } } 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(); } }
这样就完成的遥控器了,个人觉得充分理解实例二的思想就可以了,这其实也是针对接口编程,而不是实现,并且运动了组合的思想。
相关文章推荐
- iBokan_ios80_自学系列_1(部分循环结构)
- [DM]OMA DM RepPro 协议学习
- 操作系统启动区的疑点理解
- Objective-C面试题2
- [Android] 内存泄漏调试经验分享
- 两款Docker管理UI:DockerUI & Shipyard
- 浅谈windows 编程中SendMessage函数的妙用!!!
- Now, schedule !
- [读书]为什么从现在开始要写博客?
- 《浪潮之巅》读书笔记1
- 面向对象程序设计
- Roman to Integer
- Roman to Integer
- 优美英文写作摘录
- Theano2.1.3-基础知识之更多的例子
- Objective-C面试题
- 面向对象程序设计
- winXP电脑周围的无线网连不上怎么办?
- Android 本地代码如何输出日志
- 树莓派的GPIO介绍