当前位置: 代码迷 >> 综合 >> HeadFirst(六)Command 命令设计模式
  详细解决方案

HeadFirst(六)Command 命令设计模式

热度:62   发布时间:2024-01-10 04:43:21.0

 

命令模式

将“请求”封装成对象,以便使用不同的请求,队列或日志来参数化其它对象。

命令模式也可以支持撤销的操作。

 

使用命令模式来实现“队列、日志、支持撤销操作”

 



 

===========================================================================

 

示例:遥控器功能的实现---开/关/撤销

 



 

 

接收命令的对象

 

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;}@Overridepublic void execute() {light.off();}@Overridepublic 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;}@Overridepublic void execute() {light.on();}@Overridepublic 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;}@Overridepublic void execute() {garageDoor.down();}@Overridepublic 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;}@Overridepublic void execute() {garageDoor.up();}@Overridepublic 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;}@Overridepublic void execute() {stereo.off();}@Overridepublic 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;}@Overridepublic void execute() {stereo.on();}@Overridepublic 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;}@Overridepublic void execute() {preSpeed = ceilingFan.getSpeed();run(CeilingFan.HIGH);}@Overridepublic 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;}@Overridepublic void execute() {preSpeed = ceilingFan.getSpeed();run(CeilingFan.MEDIUM);}@Overridepublic 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;}@Overridepublic void execute() {preSpeed = ceilingFan.getSpeed();run(CeilingFan.LOW);}@Overridepublic 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;}@Overridepublic void execute() {preSpeed = ceilingFan.getSpeed();run(CeilingFan.OFF);}@Overridepublic 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;}@Overridepublic void execute() {for(Command c : commands) {c.execute();}}@Overridepublic 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();}

 

 

 

 

  相关解决方案