《Head First设计模式》Eric Freeman;Elisabeth Freeman;Kathy Sierra;Bert Bates
中国电力出版社
ISBN:9787508353937
命令模式-将“请求”封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。
命令模式代码示例:
Command接口
- package net.dp.command.simpleremote;
- public interface Command {
- public void execute();
- }
所要封装的两个事物GarageDoor和Light(Receiver)
- package net.dp.command.simpleremote;
- public class GarageDoor {
- public GarageDoor() {
- }
- public void up() {
- System.out.println("Garage Door is Open");
- }
- public void down() {
- System.out.println("Garage Door is Closed");
- }
- public void stop() {
- System.out.println("Garage Door is Stopped");
- }
- public void lightOn() {
- System.out.println("Garage light is on");
- }
- public void lightOff() {
- System.out.println("Garage light is off");
- }
- }
- package net.dp.command.simpleremote;
- public class Light {
- public Light() {
- }
- public void on() {
- System.out.println("Light is on");
- }
- public void off() {
- System.out.println("Light is off");
- }
- }
封装的具体命令(ConcreteCommand)
- package net.dp.command.simpleremote;
- public class GarageDoorOpenCommand implements Command {
- GarageDoor garageDoor;
- public GarageDoorOpenCommand(GarageDoor garageDoor) {
- this.garageDoor = garageDoor;
- }
- public void execute() {
- garageDoor.up();
- }
- }
- package net.dp.command.simpleremote;
- public class LightOnCommand implements Command {
- Light light;
- public LightOnCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- light.on();
- }
- }
- package net.dp.command.simpleremote;
- public class LightOffCommand implements Command {
- Light light;
- public LightOffCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- light.off();
- }
- }
下面是Invoker
- package net.dp.command.simpleremote;
- //
- // This is the invoker
- //
- public class SimpleRemoteControl {
- Command slot;
- public SimpleRemoteControl() {}
- public void setCommand(Command command) {
- slot = command;
- }
- public void buttonWasPressed() {
- slot.execute();
- }
- }
调用关系
- package net.dp.command.simpleremote;
- public class RemoteControlTest {
- public static void main(String[] args) {
- SimpleRemoteControl remote = new SimpleRemoteControl();
- Light light = new Light();
- GarageDoor garageDoor = new GarageDoor();
- LightOnCommand lightOn = new LightOnCommand(light);
- GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);
- remote.setCommand(lightOn);
- remote.buttonWasPressed();
- remote.setCommand(garageOpen);
- remote.buttonWasPressed();
- }
- }
下面是带有undo功能的命令模式示例
Command接口
- package net.dp.command.undo;
- public interface Command {
- public void execute();
- public void undo();
- }
所要封装的两个事物CeilingFan和Light(Receiver)
- package net.dp.command.undo;
- 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(location + " ceiling fan is on high");
- }
- public void medium() {
- speed = MEDIUM;
- System.out.println(location + " ceiling fan is on medium");
- }
- public void low() {
- speed = LOW;
- System.out.println(location + " ceiling fan is on low");
- }
- public void off() {
- speed = OFF;
- System.out.println(location + " ceiling fan is off");
- }
- public int getSpeed() {
- return speed;
- }
- }
- package net.dp.command.undo;
- public class Light {
- String location;
- int level;
- public Light(String location) {
- this.location = location;
- }
- public void on() {
- level = 100;
- System.out.println("Light is on");
- }
- public void off() {
- level = 0;
- System.out.println("Light is off");
- }
- public void dim(int level) {
- this.level = level;
- if (level == 0) {
- off();
- }
- else {
- System.out.println("Light is dimmed to " + level + "%");
- }
- }
- public int getLevel() {
- return level;
- }
- }
封装的具体命令(ConcreteCommand)
这里为了实现undo(),在execute()执行之前,会保存之前的对象状态。
- package net.dp.command.undo;
- public class CeilingFanHighCommand implements Command {
- CeilingFan ceilingFan;
- int prevSpeed;
- public CeilingFanHighCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- prevSpeed = ceilingFan.getSpeed();
- ceilingFan.high();
- }
- public void undo() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
- package net.dp.command.undo;
- 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() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
- package net.dp.command.undo;
- public class CeilingFanLowCommand implements Command {
- CeilingFan ceilingFan;
- int prevSpeed;
- public CeilingFanLowCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- prevSpeed = ceilingFan.getSpeed();
- ceilingFan.low();
- }
- public void undo() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
- package net.dp.command.undo;
- public class CeilingFanOnCommand implements Command {
- CeilingFan ceilingFan;
- public CeilingFanOnCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- ceilingFan.high();
- }
- public void undo() {
- ceilingFan.off();
- }
- }
- package net.dp.command.undo;
- 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() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
- package net.dp.command.undo;
- public class DimmerLightOnCommand implements Command {
- Light light;
- int prevLevel;
- public DimmerLightOnCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- prevLevel = light.getLevel();
- light.dim(75);
- }
- public void undo() {
- light.dim(prevLevel);
- }
- }
- package net.dp.command.undo;
- public class DimmerLightOffCommand implements Command {
- Light light;
- int prevLevel;
- public DimmerLightOffCommand(Light light) {
- this.light = light;
- prevLevel = 100;
- }
- public void execute() {
- prevLevel = light.getLevel();
- light.off();
- }
- public void undo() {
- light.dim(prevLevel);
- }
- }
- package net.dp.command.undo;
- public class LightOnCommand implements Command {
- Light light;
- public LightOnCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- light.on();
- }
- public void undo() {
- light.off();
- }
- }
- package net.dp.command.undo;
- public class LightOffCommand implements Command {
- Light light;
- public LightOffCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- light.off();
- }
- public void undo() {
- light.on();
- }
- }
下面是一个空对象(null object)。可以将处理null的责任转移给空对象。举例来说,遥控器不可能一出厂就设置了有意义的命令对象,所以提供了NoCommand对象作为代用品,当调用它的execute()时,它不会做任何事情。
- package net.dp.command.undo;
- public class NoCommand implements Command {
- public void execute() { }
- public void undo() { }
- }
下面是Invoker
- package net.dp.command.undo;
- //
- // This is the invoker
- //
- 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------ 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() + "\n");
- return stringBuff.toString();
- }
- }
调用关系
- package net.dp.command.undo;
- public class RemoteLoader {
- public static void main(String[] args) {
- RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
- Light livingRoomLight = new Light("Living Room");
- LightOnCommand livingRoomLightOn =
- new LightOnCommand(livingRoomLight);
- LightOffCommand livingRoomLightOff =
- new LightOffCommand(livingRoomLight);
- remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
- remoteControl.onButtonWasPushed(0);
- remoteControl.offButtonWasPushed(0);
- System.out.println(remoteControl);
- remoteControl.undoButtonWasPushed();
- remoteControl.offButtonWasPushed(0);
- remoteControl.onButtonWasPushed(0);
- System.out.println(remoteControl);
- remoteControl.undoButtonWasPushed();
- CeilingFan ceilingFan = new CeilingFan("Living Room");
- CeilingFanMediumCommand ceilingFanMedium =
- new CeilingFanMediumCommand(ceilingFan);
- CeilingFanHighCommand ceilingFanHigh =
- new CeilingFanHighCommand(ceilingFan);
- CeilingFanOffCommand ceilingFanOff =
- new CeilingFanOffCommand(ceilingFan);
- remoteControl.setCommand(0, ceilingFanMedium, ceilingFanOff);
- remoteControl.setCommand(1, ceilingFanHigh, ceilingFanOff);
- remoteControl.onButtonWasPushed(0);
- remoteControl.offButtonWasPushed(0);
- System.out.println(remoteControl);
- remoteControl.undoButtonWasPushed();
- remoteControl.onButtonWasPushed(1);
- System.out.println(remoteControl);
- remoteControl.undoButtonWasPushed();
- }
- }
设置宏命令,可以将部分命令组合在一起依次连续触发或关闭
- package net.dp.command.party;
- public class MacroCommand implements Command {
- Command[] commands;
- public MacroCommand(Command[] commands) {
- this.commands = commands;
- }
- public void execute() {
- for (int i = 0; i < commands.length; i++) {
- commands[i].execute();
- }
- }
- public void undo() {
- for (int i = 0; i < commands.length; i++) {
- commands[i].undo();
- }
- }
- }
调用关系
- package net.dp.command.party;
- public class RemoteLoader {
- public static void main(String[] args) {
- RemoteControl remoteControl = new RemoteControl();
- Light light = new Light("Living Room");
- TV tv = new TV("Living Room");
- Stereo stereo = new Stereo("Living Room");
- Hottub hottub = new Hottub();
- LightOnCommand lightOn = new LightOnCommand(light);
- StereoOnCommand stereoOn = new StereoOnCommand(stereo);
- TVOnCommand tvOn = new TVOnCommand(tv);
- HottubOnCommand hottubOn = new HottubOnCommand(hottub);
- LightOffCommand lightOff = new LightOffCommand(light);
- StereoOffCommand stereoOff = new StereoOffCommand(stereo);
- TVOffCommand tvOff = new TVOffCommand(tv);
- HottubOffCommand hottubOff = new HottubOffCommand(hottub);
- Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};
- Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};
- MacroCommand partyOnMacro = new MacroCommand(partyOn);
- MacroCommand partyOffMacro = new MacroCommand(partyOff);
- remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
- System.out.println(remoteControl);
- System.out.println("--- Pushing Macro On---");
- remoteControl.onButtonWasPushed(0);
- System.out.println("--- Pushing Macro Off---");
- remoteControl.offButtonWasPushed(0);
- }
- }
《Head First Design Pattern》源代码下载 http://zhangjunhd.blog.51cto.com/113473/69908
本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/409996