HeadFirst 命令模式 风扇撤回课本实现错误代码及利用栈的解决办法

        按照《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 命令模式 风扇课本实现错误代码及利用栈的解决办法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值