您的位置:首页 > 其它

命令模式

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();
}
}


这样就完成的遥控器了,个人觉得充分理解实例二的思想就可以了,这其实也是针对接口编程,而不是实现,并且运动了组合的思想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: