按照《HeadFirst JAVA设计模式》课本中代码实现命令模式的风扇命令是存在错误的。这里给出得出错误结果的样例,即为依次打开风扇1、3、2、3档,然后依次撤回命令四次。其输出结果期望的风扇档数为1、3、2、3、2、3、1、0,而实际输出结果为1、3、2、3、2、3、2、0。
课本代码测试样例截图:
课本代码测试样例结果输出截图:
课本代码测试错误说明:
这里样例是先设置风扇1级、3级、2级、3级,然后连续undo四次。
undo命令本应设置风扇为2级、3级、1级、0级(关闭),
而实际undo结果是设置风扇为2级、3级、2级、0级(关闭)。出现错误。
出现此错误的原因是3级命令的前置命令只记录了2级,之前的1级命令被覆盖掉了。
解决办法简要说明:
用栈存储风扇命令的所有前置命令任务。更改后得到结果如下:
以此纪念与JAVA老师交流的美好时光。
具体实现代码:
Command.java
package commandStack;
public abstract class Command {
public Command(){}
public abstract void execute();
public abstract void undo();
}
CeilingFanHighCommand.java
package commandStack;
import java.util.Stack;
public class CeilingFanHighCommand extends Command{
CeilingFan ceilingFan;
Stack<Integer> prevSpeed;
public CeilingFanHighCommand(CeilingFan ceilingFan)
{
this.ceilingFan = ceilingFan;
prevSpeed = new Stack<Integer>();
}
@Override
public void execute() {
// TODO Auto-generated method stub
prevSpeed.push(ceilingFan.getSpeed());
ceilingFan.high();
}
@Override
public void undo() {
// TODO Auto-generated method stub
if(prevSpeed.size()>0)
{
int i = prevSpeed.pop();
if(i == CeilingFan.HIGH)
{
ceilingFan.high();
}
else if(i == CeilingFan.MEDIUM)
{
ceilingFan.medium();
}
else if(i == CeilingFan.LOW)
{
ceilingFan.low();
}
else if(i == CeilingFan.OFF)
{
ceilingFan.off();
}
}
}
}
CeilFanMediumCommand.java
package commandStack;
import java.util.Stack;
public class CeilFanMediumCommand extends Command{
CeilingFan ceilingFan;
Stack<Integer> prevSpeed; //更改处
public CeilFanMediumCommand(CeilingFan ceilingFan)
{
this.ceilingFan = ceilingFan;
prevSpeed = new Stack<Integer>(); //更改处
}
@Override
public void execute() {
// TODO Auto-generated method stub
prevSpeed.push(ceilingFan.getSpeed()); //更改处
ceilingFan.medium();
}
@Override
public void undo() {
// TODO Auto-generated method stub
if(prevSpeed.size()>0) //更改处
{
int i = prevSpeed.pop();
if(i == CeilingFan.HIGH)
{
ceilingFan.high();
}
else if(i == CeilingFan.MEDIUM)
{
ceilingFan.medium();
}
else if(i == CeilingFan.LOW)
{
ceilingFan.low();
}
else if(i == CeilingFan.OFF)
{
ceilingFan.off();
}
}
}
}
CeilingFanLowCommand.java
package commandStack;
import java.util.Stack;
public class CeilingFanLowCommand extends Command{
CeilingFan ceilingFan;
Stack<Integer> prevSpeed;
public CeilingFanLowCommand(CeilingFan ceilingFan) {
prevSpeed = new Stack<Integer>();
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
// TODO Auto-generated method stub
prevSpeed.push(ceilingFan.getSpeed());
ceilingFan.low();
}
@Override
public void undo() {
// TODO Auto-generated method stub
if(prevSpeed.size()>0)
{
int i = prevSpeed.pop();
//System.out.println(i+"-----");
if(i == CeilingFan.HIGH)
{
ceilingFan.high();
}
else if(i == CeilingFan.MEDIUM)
{
ceilingFan.medium();
}
else if(i == CeilingFan.LOW)
{
ceilingFan.low();
}
else if(i == CeilingFan.OFF)
{
ceilingFan.off();
}
}
}
}
CeilingFanOffCommand.java
package commandStack;
import java.util.Stack;
public class CeilingFanOffCommand extends Command{
CeilingFan ceilingFan;
Stack<Integer> prevSpeed;
public CeilingFanOffCommand(CeilingFan ceilingFan)
{
prevSpeed = new Stack<Integer>();
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
// TODO Auto-generated method stub
prevSpeed.push(ceilingFan.getSpeed());
ceilingFan.off();
}
@Override
public void undo() {
// TODO Auto-generated method stub
if(prevSpeed.size()>0)
{
int i = prevSpeed.pop();
if(i == CeilingFan.HIGH)
{
ceilingFan.high();
}
else if(i == CeilingFan.MEDIUM)
{
ceilingFan.medium();
}
else if(i == CeilingFan.LOW)
{
ceilingFan.low();
}
else if(i == CeilingFan.OFF)
{
ceilingFan.off();
}
}
}
}
NoCommand.java
package commandStack;
public class NoCommand extends Command {
public void execute() { }
public void undo() { }
}
CeilingFan.java
package commandStack;
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;
System.out.println("风扇1级");
}
public void medium()
{
speed = MEDIUM;
System.out.println("风扇2级");
}
public void low()
{
speed = LOW;
System.out.println("风扇3级");
}
public void off()
{
speed = OFF;
System.out.println("风扇0级");
}
public int getSpeed()
{
return speed;
}
}
RemoteControl.java
package commandStack;
import java.util.Stack;
//
// This is the invoker
//
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
Command redoCommand;
static Stack<Command> undoStack;
static Stack<Command> redoStack;
public RemoteControl() {
undoStack = new Stack<Command>();
redoStack = new Stack<Command>();
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;
redoCommand = noCommand;
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot) {
onCommands[slot].execute();
undoStack.add(onCommands[slot]);
//undoCommand = onCommands[slot];
}
public void offButtonWasPushed(int slot) {
offCommands[slot].execute();
undoStack.add(offCommands[slot]);
//undoCommand = offCommands[slot];
}
public void undoButtonWasPushed() {
//undoCommand.undo();
if(undoStack.size()>=1)
{
Command cmd = undoStack.pop();
cmd.undo();
redoStack.add(cmd);
}
}
public void redoButtonWasPushed() {
//undoCommand.undo();
if(redoStack.size()>=1)
{
Command cmd = redoStack.pop();
cmd.execute();
undoStack.add(cmd);
}
}
}
RemoteLoader.java
package commandStack;
public class RemoteLoader {
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
CeilingFan ceilingFan = new CeilingFan("Living Room");
CeilingFanHighCommand ceilingFanHighCommand = new CeilingFanHighCommand(ceilingFan);
CeilFanMediumCommand ceilingFanMediumCommand = new CeilFanMediumCommand(ceilingFan);
CeilingFanLowCommand ceilingFanLowCommand = new CeilingFanLowCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOffCommand = new CeilingFanOffCommand(ceilingFan);
remoteControl.setCommand(1, ceilingFanHighCommand, ceilingFanOffCommand);
remoteControl.setCommand(2, ceilingFanMediumCommand, ceilingFanOffCommand);
remoteControl.setCommand(3, ceilingFanLowCommand, ceilingFanOffCommand);
remoteControl.onButtonWasPushed(1);
remoteControl.onButtonWasPushed(3);
remoteControl.onButtonWasPushed(2);
remoteControl.onButtonWasPushed(3);
remoteControl.undoButtonWasPushed();
remoteControl.undoButtonWasPushed();
remoteControl.undoButtonWasPushed();
remoteControl.undoButtonWasPushed();
//打印结果期望是 1 3 2 3 2 3 1 0
//打印结果实际是1 3 2 3 2 3 1 0
//正确!!
}
}
一劳永逸的项目压缩包下载链接:HeadFirst 命令模式 风扇课本实现错误代码及利用栈的解决办法