命令模式
将“请求”封装成对象,以便使用不同的请求,队列或日志来参数化其它对象。
命令模式也可以支持撤销的操作。
使用命令模式来实现“队列、日志、支持撤销操作”
===========================================================================
示例:遥控器功能的实现---开/关/撤销
接收命令的对象
package receiver; public abstract class Receiver { protected String location; }
package receiver.impl; import receiver.Receiver; /** * 灯 */ public class Light extends Receiver { public Light(String location) { this.location = location; } public void on() { System.out.println(location+"light on"); } public void off() { System.out.println(location+"light off"); } }
package receiver.impl; import receiver.Receiver; /** * 车库门 */ public class GarageDoor extends Receiver { public GarageDoor(String location) { this.location = location; } public void up() { System.out.println("Grarge Door is open"); } public void down() { System.out.println("Grarge Door is close"); } }
package receiver.impl; import receiver.Receiver; /** * 音响 */ public class Stereo extends Receiver { public Stereo(String location) { this.location = location; } public void on() { System.out.println("stereo is open,put cd in,set volume 11"); } public void off() { System.out.println("stereo off"); } }
各种具体的命令
package command; /** * 命令对象,对外只暴露execute(),内部如何执行外界无需关心 */ public abstract interface Command { //执行指令 public abstract void execute(); //撤销上一步操作 public abstract void undo(); }
package command.impl; import receiver.impl.Light; import command.Command; public class LightOffCommand implements Command { Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.off(); } @Override public void undo() { light.on(); } }
package command.impl; import receiver.impl.Light; import command.Command; 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 command.impl; import receiver.impl.GarageDoor; import command.Command; public class GarageDoorDownCommand implements Command { GarageDoor garageDoor; public GarageDoorDownCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } @Override public void execute() { garageDoor.down(); } @Override public void undo() { garageDoor.up(); } }
package command.impl; import receiver.impl.GarageDoor; import command.Command; public class GarageDoorUpCommand implements Command { GarageDoor garageDoor; public GarageDoorUpCommand(GarageDoor garageDoor) { this.garageDoor = garageDoor; } @Override public void execute() { garageDoor.up(); } @Override public void undo() { garageDoor.down(); } }
package command.impl; import receiver.impl.Stereo; import command.Command; public class StereoOffCommand implements Command { Stereo stereo; public StereoOffCommand(Stereo stereo) { this.stereo = stereo; } @Override public void execute() { stereo.off(); } @Override public void undo() { stereo.on(); } }
package command.impl; import receiver.impl.Stereo; import command.Command; public class StereoOnWithCDCommand implements Command { Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this.stereo = stereo; } @Override public void execute() { stereo.on(); } @Override public void undo() { stereo.off(); } }
命令调用者---Invoker
完成命令的绑定
负责将命令绑定到对应的具体对象上去执行
package controller; import java.util.Arrays; import command.Command; import command.NoCommand; /** * 遥控器---Invoker * 负责发出各种命令 */ public class RemoteController { //一组开的命令 Command[] onCommands; //一组关的命令 Command[] offCommands; //记录上次执行的命令,以便完成撤销 Command undoCommand; public RemoteController() { init(); } /** * 初始化遥控器 */ private void init() { onCommands = new Command[7];//看到没有,“接口也可以new”! offCommands = new Command[7]; Command noCommand = new NoCommand(); Arrays.fill(onCommands, noCommand); Arrays.fill(offCommands, noCommand); undoCommand = noCommand; } /** * 为每个插槽指定对应的命令对象 * @param slot 插槽序号 * @param onCommand 开 * @param offCommand 关 */ public void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } /** * 事件触发,执行对应的命令 * @param slot 扩展槽序号 */ public void onButtonPressed(int slot) { onCommands[slot].execute();//执行命令 undoCommand = onCommands[slot];//记录本次执行的命令对象 } /** * 事件触发,执行对应的命令 * @param slot 扩展槽序号 */ public void offButtonPressed(int slot) { offCommands[slot].execute();//执行命令 undoCommand = offCommands[slot];//记录本次执行的命令对象 } /** * 撤销 */ public void undoButtonPressed() { undoCommand.undo(); } /** * 输出遥控器各个扩展槽所绑定的命令对象 */ public String toString() { StringBuffer stringBuff = new StringBuffer(); stringBuff.append("----- 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()); return stringBuff.toString(); } }
测试
package test; import receiver.impl.GarageDoor; import receiver.impl.Light; import receiver.impl.Stereo; import command.impl.GarageDoorDownCommand; import command.impl.GarageDoorUpCommand; import command.impl.LightOffCommand; import command.impl.LightOnCommand; import command.impl.StereoOffCommand; import command.impl.StereoOnWithCDCommand; import controller.RemoteController; public class RemoteLoader { public static void main(String[] args) { testCommand(); testUndo(); } private static void testCommand() { //Invoker---遥控器 RemoteController remoteController = new RemoteController(); //Receiver---各种被控制的对象 Light livingRoomLight = new Light("Living Room"); Light kitchenLight = new Light("Kitchen"); GarageDoor garageDoor = new GarageDoor(""); Stereo stereo = new Stereo("Living Room"); //为每个插槽绑定命令 remoteController.setCommand(0, new LightOnCommand(livingRoomLight), new LightOffCommand(livingRoomLight)); remoteController.setCommand(1, new LightOnCommand(kitchenLight), new LightOffCommand(kitchenLight)); remoteController.setCommand(2, new GarageDoorUpCommand(garageDoor), new GarageDoorDownCommand(garageDoor)); remoteController.setCommand(3, new StereoOnWithCDCommand(stereo), new StereoOffCommand(stereo)); //查看遥控器每个插槽所绑定的命令 System.out.println(remoteController); //测试遥控器插槽对应的命令 remoteController.onButtonPressed(0); remoteController.offButtonPressed(0); remoteController.onButtonPressed(1); remoteController.offButtonPressed(1); remoteController.onButtonPressed(2); remoteController.offButtonPressed(2); remoteController.onButtonPressed(3); remoteController.offButtonPressed(3); } private static void testUndo() { //Invoker---遥控器 RemoteController remoteController = new RemoteController(); //命令接收对象 Light livingRoomLight = new Light("Living Room"); //命令 LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight); LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight); //将卧室灯的命令绑定到0号插槽 remoteController.setCommand(0, livingRoomLightOn, livingRoomLightOff); remoteController.onButtonPressed(0);//开 remoteController.offButtonPressed(0);//关 System.out.println(remoteController); remoteController.undoButtonPressed();//撤销->开 remoteController.offButtonPressed(0);//关 remoteController.onButtonPressed(0);//开 remoteController.onButtonPressed(0);//开 System.out.println(remoteController); remoteController.undoButtonPressed(); } }
===========================================================================
使用状态实现撤销
package receiver.impl; import receiver.Receiver; public class CeilingFan extends Receiver{ public static final int HIGH = 3; public static final int MEDIUM = 2; public static final int LOW = 1; public static final int OFF = 0; int speed;//当前速度 public CeilingFan(String location) { this.location = location; } public void high() { speed = HIGH; System.out.println("高速狂转"); } public void medium() { speed = MEDIUM; System.out.println("中速转动"); } public void low() { speed = LOW; System.out.println("慢速转动"); } public void off() { speed = OFF; System.out.println("停止转动"); } public int getSpeed() { return speed; } }
package command.impl; import receiver.impl.CeilingFan; import command.Command; public class CeilingFanHighCommand implements Command { CeilingFan ceilingFan; int preSpeed;//上一次的速度【如果使用堆栈记录信息,可以实现多层次的撤销】 public CeilingFanHighCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } @Override public void execute() { preSpeed = ceilingFan.getSpeed(); run(CeilingFan.HIGH); } @Override public void undo() { run(preSpeed); } private void run(int speed) { switch(speed) { 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 command.impl; import receiver.impl.CeilingFan; import command.Command; public class CeilingFanMediumCommand implements Command { CeilingFan ceilingFan; int preSpeed; public CeilingFanMediumCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } @Override public void execute() { preSpeed = ceilingFan.getSpeed(); run(CeilingFan.MEDIUM); } @Override public void undo() { run(preSpeed); } private void run(int speed) { switch(speed) { 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 command.impl; import receiver.impl.CeilingFan; import command.Command; public class CeilingFanLowCommand implements Command { CeilingFan ceilingFan; int preSpeed; public CeilingFanLowCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } @Override public void execute() { preSpeed = ceilingFan.getSpeed(); run(CeilingFan.LOW); } @Override public void undo() { run(preSpeed); } private void run(int speed) { switch(speed) { 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 command.impl; import receiver.impl.CeilingFan; import command.Command; public class CeilingFanOffCommand implements Command { CeilingFan ceilingFan; int preSpeed;//跟踪上一次的运行状态 public CeilingFanOffCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } @Override public void execute() { preSpeed = ceilingFan.getSpeed(); run(CeilingFan.OFF); } @Override public void undo() { run(preSpeed); } private void run(int speed) { switch(speed) { case CeilingFan.HIGH: ceilingFan.high(); break; case CeilingFan.MEDIUM: ceilingFan.medium(); break; case CeilingFan.LOW: ceilingFan.low(); break; case CeilingFan.OFF: ceilingFan.off(); break; } } }
测试
private static void testCeilingFan() { RemoteController invoker = new RemoteController(); CeilingFan ceilingFan = new CeilingFan("Living Room"); CeilingFanHighCommand ceilingHighCmd = new CeilingFanHighCommand(ceilingFan); CeilingFanMediumCommand ceilingMediumCmd = new CeilingFanMediumCommand(ceilingFan); CeilingFanLowCommand ceilingLowCmd = new CeilingFanLowCommand(ceilingFan); CeilingFanOffCommand ceilingOffCmd = new CeilingFanOffCommand(ceilingFan); invoker.setCommand(0, ceilingHighCmd, ceilingOffCmd); invoker.setCommand(1, ceilingMediumCmd, ceilingOffCmd); invoker.setCommand(2, ceilingLowCmd, ceilingOffCmd); invoker.onButtonPressed(0); invoker.offButtonPressed(0); invoker.undoButtonPressed(); invoker.onButtonPressed(2); invoker.onButtonPressed(1); invoker.undoButtonPressed(); }
===========================================================================
Party模式
把命令对象封装到一个数组中,完成命令的批量执行
package command.impl; import command.Command; /** * Party模式 * 宏命令:将一组命令集合起来,一起执行 */ public class MacroCommand implements Command { Command[] commands; public MacroCommand(Command[] commands) { this.commands = commands; } @Override public void execute() { for(Command c : commands) { c.execute(); } } @Override public void undo() { for(Command c : commands) { c.undo(); } } }
测试
private static void testMacroCommand() { RemoteController remoteController = new RemoteController(); Light light = new Light("Living Room"); Stereo stereo = new Stereo(""); CeilingFan ceilingFan = new CeilingFan("Living Room"); LightOnCommand lightOn = new LightOnCommand(light); StereoOnWithCDCommand stereoOn = new StereoOnWithCDCommand(stereo); CeilingFanMediumCommand celingFanMedium = new CeilingFanMediumCommand(ceilingFan); LightOffCommand lightOff = new LightOffCommand(light); StereoOffCommand stereoOff = new StereoOffCommand(stereo); CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan); Command[] partyOn = {lightOn, stereoOn, celingFanMedium}; Command[] partyOff = {lightOff, stereoOff, ceilingFanOff}; MacroCommand partyOnMacro = new MacroCommand(partyOn); MacroCommand partyOffMacro = new MacroCommand(partyOff); remoteController.setCommand(0, partyOnMacro, partyOffMacro); // remoteController.onButtonPressed(0); remoteController.offButtonPressed(0); remoteController.undoButtonPressed(); }
相关推荐
在Head First 设计模式这本书中,第六章详细介绍了如何在C++中实现命令模式。 命令模式的核心思想是将"做什么"与"谁去做"分离开来。命令对象持有接收者并调用其特定方法,而调用者只关心命令对象,而不关心具体的...
总结来说,Headfirst第六章的命令模式C++实现涵盖了设计模式中的核心概念:解耦、多态和对象的职责分离。通过这种方式,我们可以构建更加灵活、可扩展的系统。学习和应用命令模式能帮助我们编写出更易于维护和测试的...
《Headfirst设计模式》是一本深受开发者欢迎的设计模式学习书籍,尤其对于初学者而言,其独特的教学方式使得复杂的概念变得易于理解。这本书以其高清的中文版PDF格式提供,结合书中源码,为读者提供了深入实践的可能...
【行为模式】Head First 设计模式之命令模式(Command) 命令模式是一种行为设计模式,它将请求封装为一个对象,从而使我们能支持可撤销的操作、参数化对象以及将请求排队等高级操作。在Head First的设计模式书中,...
总的来说,这个压缩包包含的资源可以帮助你深入理解设计模式,通过《HeadFirst设计模式》和《HeadFirst in Java》的源码,你可以学习到如何在实际项目中应用这些模式。而UML类图则提供了直观的视角,便于你把握设计...
第1章到第11章陆续介绍的设计模式为Strategy、Observer、Decorator、Abstract Factory、Factory Method、Singleton、Command、Adapter、Facade、Template Method、iterator、Composite、State、proxy。最后三章比较...
《Head First设计模式》是一本深受开发者欢迎的设计模式教程,以其独特的视觉呈现方式和易于理解的语言,让初学者也能快速掌握设计模式的核心概念。这本书深入浅出地介绍了23种GOF(GoF,Gamma、Erich、Johnson、...
《Head First 设计模式》的英文版是一本面向初学者的设计模式入门书籍,它以幽默风趣的文风,深入浅出地介绍了软件设计中经常使用的设计模式。设计模式是一套被反复使用、多数人知晓、经过分类编目、代码设计经验的...
《Head First 设计模式》是一本深受欢迎的设计模式书籍,由Eric Freeman、Elisabeth Robson、Bert Bates和Kathy Sierra合著。这本书以其独特的视觉呈现方式和易理解的教学方法,深受程序员们的喜爱,尤其是那些希望...
《HeadFirst设计模式JAVA版源码》是一份深入学习设计模式的重要资源,它基于流行的编程语言Java,旨在帮助开发者理解并应用设计模式于实际项目中。设计模式是软件工程中的重要概念,它代表了在特定场景下解决问题的...
《Head First设计模式》是软件开发领域的一本经典著作,主要介绍了面向对象设计中的各种模式。这本书通过生动、直观的方式,使读者能够更好地理解和应用设计模式。源代码是书中理论知识的具体实现,可以帮助读者深入...
《Head First设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第11章陆续介绍的设计模式为Strategy、Observer、Decorator、...
《Head First设计模式》是一本深受开发者欢迎的设计模式学习书籍,以其独特的教学方式,通过丰富的图解和幽默的语言,帮助读者深入理解设计模式的核心概念。这本书的官方源码提供了书中所讲解的每个设计模式的实际...
《Head First设计模式》是一本深受程序员喜爱的书籍,它以独特的方式讲解了设计模式这一核心的编程概念。设计模式是软件开发中的经验总结,是解决常见问题的有效模板,可以帮助开发者编写可维护、可扩展、易理解的...
《HeadFirst设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第11章陆续介绍的设计模式为Strategy、Observer、Decorator、...
《Head First设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第11章陆续介绍的设计模式为Strategy、Observer、Decorator、...
《Head First设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第 11章陆续介绍的设计 5b4 式为Strategy、Observer、Decorator、...
《Head First设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第11章陆续介绍的设计模式为Strategy、Observer、Decorator、...
《Head First 设计模式》是软件开发领域内一本广受欢迎的书籍,由Eric Freeman、Elisabeth Robson、Bert Bates和Kathy Sierra四位作者共同撰写。这本书以其独特的视觉风格和易于理解的教学方法,深入浅出地介绍了...