继续上部分的说
在之前的文章最后写了一个带有撤销电灯功能的遥控器功能,通常,想要实现撤销的功能,需要记录撤销之前的状态是什么,就比方说电扇,允许有多个风速状态,也允许被关闭。
直接上代码。1、风扇类
package CeilingFan;/** * 使用状态实现撤销 * 风扇类 * @author Joy * */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; } // 高转速 public void high() { speed = HIGH; System.out.println(location+"风扇正在高转速运行"); } // 中转速 public void medium() { speed = MEDIUM; System.out.println(location+"风扇正在中转速运行"); } // 低转速 public void low() { speed = LOW; System.out.println(location+"风扇正在低转速运行"); } // 关闭吊扇 public void off() { speed = OFF; System.out.println(location+"风扇关闭"); } //获取当前吊扇速度 public int getSpeed(){ return speed; }}
2、命令类
package CeilingFan;public interface Command { public void execute(); public void undo();}
3、下面是风扇高、中、低关闭的具体实现类
package CeilingFan;/** * 风扇高速操作 * * @author Joy * */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() { // 将风扇的速度设置为之前的状态,达到撤销目的 switch (prevSpeed) { case CeilingFan.HIGH: ceilingFan.high(); break; case CeilingFan.MEDIUM: ceilingFan.medium(); break; case CeilingFan.LOW: ceilingFan.low(); break; case CeilingFan.OFF: ceilingFan.off(); break; } }}
package CeilingFan;/** * 风扇中速操作 * @author Joy * */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() { switch (prevSpeed) { case CeilingFan.HIGH: ceilingFan.high(); break; case CeilingFan.MEDIUM: ceilingFan.medium(); break; case CeilingFan.LOW: ceilingFan.low(); break; default: ceilingFan.off(); break; } }}
package CeilingFan;/** * 风扇低速操作 * @author Joy * */public class CeilingFanLowCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanLowCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } @Override public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.low(); } @Override public void undo() { switch (prevSpeed) { case CeilingFan.HIGH: ceilingFan.high(); break; case CeilingFan.MEDIUM: ceilingFan.medium(); break; case CeilingFan.LOW: ceilingFan.low(); break; default: ceilingFan.off(); break; } }}
package CeilingFan;/** * 风扇关闭 * @author Joy * */public class CeilingFanOffCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanOffCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.off(); } public void undo() { switch (prevSpeed) { case CeilingFan.HIGH: ceilingFan.high(); break; case CeilingFan.MEDIUM: ceilingFan.medium(); break; case CeilingFan.LOW: ceilingFan.low(); break; default: ceilingFan.off(); break; } }}
4、无操作类接口
package CeilingFan;public class NoCommand implements Command { public void execute() { } public void undo() { }}
5、调用者
package CeilingFan;/** * 调用者 * @author Joy * */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------ 遥控器 -------\n"); for (int i = 0; i < onCommands.length; i++) { stringBuff.append("[插槽 " + i + "] " + onCommands[i].getClass().getName() + " " + offCommands[i].getClass().getName() + "\n"); } stringBuff.append("[撤销] " + undoCommand.getClass().getName() + "\n"); return stringBuff.toString(); }}
6、测试类
package CeilingFan;public class TestMain { public static void main(String[] args) { //实例化遥控器 RemoteControlWithUndo remoteControl=new RemoteControlWithUndo(); CeilingFan ceilingFan=new CeilingFan("卧室"); //这里高中低速 关闭分别实例化 CeilingFanHighCommand highCommand=new CeilingFanHighCommand(ceilingFan); CeilingFanMediumCommand mediumCommand=new CeilingFanMediumCommand(ceilingFan); CeilingFanLowCommand lowCommand=new CeilingFanLowCommand(ceilingFan); CeilingFanOffCommand offCommand=new CeilingFanOffCommand(ceilingFan); //遥控器加载中速和高速的开启和关闭方法 remoteControl.setCommand(0, mediumCommand, offCommand); remoteControl.setCommand(1, highCommand, offCommand); //先以中速开启吊扇 remoteControl.onButtonWasPushed(0); //关闭吊扇 remoteControl.offButtonWasPushed(0); //显示插槽调用信息 System.out.println(remoteControl.toString()); //撤销,会变为中速 remoteControl.undoButtonWasPushed(); remoteControl.onButtonWasPushed(1); System.out.println(remoteControl.toString()); remoteControl.undoButtonWasPushed(); }}
7、效果图
其实命令模式还能用于宏命令,队列请求,日志请求,命令模式我理解的很一般,往后我还会补充修改此篇内容。
要点:
1:命令模式将发出请求的对象和执行请求的对象解耦。2:被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组对象3:调用者通过调用命令对象的execute方法发出请求,这会使得的接收者的动作被调用。4:命令可以支持撤销动作,实现一个undo方法来回到execute被执行前的状态。感谢你看到这里,命令模式到这里就结束了,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~~~很快我会发布下一个设计模式的内容,生命不息,编程不止!