设计模式学习--命令模式(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