命令模式
2016-01-22 10:34
323 查看
定义:命令模式将请求封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也可支持可撤销的操作。
类图:
要点:
命令模式将发出的请求对象和执行的请求对象解耦。在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接受者一个或一组请求。
调用者通过调用命令对象的excute()发出请求。这会使得接受者的命令被调用。
调用者可以接受命令做参数。甚至在运行时动态的进行。
命令可以支持撤销。做法是实现一个undo()方法来回倒execute()被执行前的状态。
命令也可以用来实现日志和事务系统。
具体按钮:开灯/关灯按钮、暗光开/关按钮、风扇高速/中速/低速/关按钮、撤销按钮。
遥控器如下图所示:
遥控器担当请求者(或称为调用者)的角色,用RemoteControlWithUndo类实现,其内有Command[]类型的属性onCommands和offCommands表示对应的一组开关,Command类型的属性undoCommand记录最后执行的命令用于命令的撤销。遥控器上有7组开关按钮和一个撤销按钮。每个按钮对应一个具体命令,说明如下:
public void execute();
public void 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;
}
}
(2)CeilingFan风扇:
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;
}
}
[java] view plaincopy
public class NoCommand implements Command {
public void execute() { }
public void undo() { }
}
(2)LightOnCommand:开灯命令
public class LightOnCommand implements Command {
Light light;
int level;//level用于记录上次的灯光亮度
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
level = light.getLevel();
light.on();
}
public void undo() {//将灯光的亮度调到前一次的水平实现撤销
light.dim(level);
}
}
(3)LightOffCommand:关灯命令
public class LightOffCommand implements Command {
Light light;
int level;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
level = light.getLevel();
light.off();
}
public void undo() {
light.dim(level);
}
}
(4)DimmerLightOnCommand:开启暗光
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);//将灯光亮度调至75%实现暗光
}
public void undo() {
light.dim(prevLevel);
}
}
(5)DimmerLightOffCommand:关闭暗光
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);
}
}
(6)CeilingFanHighCommand:风扇高转速
public class CeilingFanHighCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;//记录以前的转速,用于撤销操作(0时表示以前的状态是:关)
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();
}
}
}
(7)CeilingFanMediumCommand:风扇中转速
public class CeilingFanMediumCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;
public CeilingFanMediumCommand(CeilingFan ceilingFan) {
this.ceilingFan = ceilingFan;
}
public void execute() {
prevSpeed = ceilingFan.getSpeed();
ceilingFan.medium();//将行为的真正执行委托给接收者,此处即ceilingFan风扇对象
}
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();
}
}
}
(8)CeilingFanLowCommand:风扇低转速
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();
}
}
}
(9)CeilingFanOffCommand:关闭风扇
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();
}
}
}
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;
}
//当编号为第slot的开On按钮按下时执行命令
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();
}
}
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);
DimmerLightOnCommand dimmerLightOnCommand=new DimmerLightOnCommand(livingRoomLight);
DimmerLightOffCommand dimmerLightOffCommand=new DimmerLightOffCommand(livingRoomLight);
CeilingFan ceilingFan = new CeilingFan("Living Room");
CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
CeilingFanLowCommand ceilingFanLow =new CeilingFanLowCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, dimmerLightOnCommand, dimmerLightOffCommand);
remoteControl.setCommand(2, ceilingFanHigh, ceilingFanOff);
remoteControl.setCommand(3, ceilingFanMedium, ceilingFanOff);
remoteControl.setCommand(4, ceilingFanLow, ceilingFanOff);
remoteControl.onButtonWasPushed(1);
remoteControl.onButtonWasPushed(3);
remoteControl.onButtonWasPushed(2);
remoteControl.offButtonWasPushed(3);
remoteControl.undoButtonWasPushed();
}
类图:
要点:
命令模式将发出的请求对象和执行的请求对象解耦。在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接受者一个或一组请求。
调用者通过调用命令对象的excute()发出请求。这会使得接受者的命令被调用。
调用者可以接受命令做参数。甚至在运行时动态的进行。
命令可以支持撤销。做法是实现一个undo()方法来回倒execute()被执行前的状态。
命令也可以用来实现日志和事务系统。
例子:
一、问题描述
使用命令模式实现遥控器,遥控器上的不同按钮控制电灯的开关及亮度、天花板风扇的开关及转速等,支持撤销。具体按钮:开灯/关灯按钮、暗光开/关按钮、风扇高速/中速/低速/关按钮、撤销按钮。
遥控器如下图所示:
遥控器担当请求者(或称为调用者)的角色,用RemoteControlWithUndo类实现,其内有Command[]类型的属性onCommands和offCommands表示对应的一组开关,Command类型的属性undoCommand记录最后执行的命令用于命令的撤销。遥控器上有7组开关按钮和一个撤销按钮。每个按钮对应一个具体命令,说明如下:
二、类图
三、代码实现
1.命令角色:Command
public interface Command {public void execute();
public void undo();//实现撤销
}
2.接收者角色:Light、CeilingFan
(1)Light电灯: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;
}
}
(2)CeilingFan风扇:
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;
}
}
3.具体命令角色:各种命令
(1)NoCommand:空命令,创建遥控器时默认其持有的都是空命令(相比判断null更好),什么事也不做[java] view plaincopy
public class NoCommand implements Command {
public void execute() { }
public void undo() { }
}
(2)LightOnCommand:开灯命令
public class LightOnCommand implements Command {
Light light;
int level;//level用于记录上次的灯光亮度
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
level = light.getLevel();
light.on();
}
public void undo() {//将灯光的亮度调到前一次的水平实现撤销
light.dim(level);
}
}
(3)LightOffCommand:关灯命令
public class LightOffCommand implements Command {
Light light;
int level;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
level = light.getLevel();
light.off();
}
public void undo() {
light.dim(level);
}
}
(4)DimmerLightOnCommand:开启暗光
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);//将灯光亮度调至75%实现暗光
}
public void undo() {
light.dim(prevLevel);
}
}
(5)DimmerLightOffCommand:关闭暗光
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);
}
}
(6)CeilingFanHighCommand:风扇高转速
public class CeilingFanHighCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;//记录以前的转速,用于撤销操作(0时表示以前的状态是:关)
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();
}
}
}
(7)CeilingFanMediumCommand:风扇中转速
public class CeilingFanMediumCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;
public CeilingFanMediumCommand(CeilingFan ceilingFan) {
this.ceilingFan = ceilingFan;
}
public void execute() {
prevSpeed = ceilingFan.getSpeed();
ceilingFan.medium();//将行为的真正执行委托给接收者,此处即ceilingFan风扇对象
}
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();
}
}
}
(8)CeilingFanLowCommand:风扇低转速
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();
}
}
}
(9)CeilingFanOffCommand:关闭风扇
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();
}
}
}
4.遥控器类,请求者(或调用者)角色,持有多个Command对象
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;
}
//当编号为第slot的开On按钮按下时执行命令
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();
}
}
5.测试
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);
DimmerLightOnCommand dimmerLightOnCommand=new DimmerLightOnCommand(livingRoomLight);
DimmerLightOffCommand dimmerLightOffCommand=new DimmerLightOffCommand(livingRoomLight);
CeilingFan ceilingFan = new CeilingFan("Living Room");
CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
CeilingFanLowCommand ceilingFanLow =new CeilingFanLowCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, dimmerLightOnCommand, dimmerLightOffCommand);
remoteControl.setCommand(2, ceilingFanHigh, ceilingFanOff);
remoteControl.setCommand(3, ceilingFanMedium, ceilingFanOff);
remoteControl.setCommand(4, ceilingFanLow, ceilingFanOff);
remoteControl.onButtonWasPushed(1);
remoteControl.onButtonWasPushed(3);
remoteControl.onButtonWasPushed(2);
remoteControl.offButtonWasPushed(3);
remoteControl.undoButtonWasPushed();
}
相关文章推荐
- java 中assert的使用
- 【百金轻】:不走寻常路
- strong、weak等详解(防止野指针)
- MAC Cocoa Opengl入门系列教程一(基本图元绘制)
- 设计模式读书笔记-----适配器模式
- ios 非常好的Demo
- 蓝欧考试UI考试绝密
- socket通信介绍
- ionic 实现双击返回键退出应用功能
- 自定义log日志
- CSS层叠样式表
- scanf的用法
- CSS或者JS实现鼠标悬停显示另一元素
- 网络编程(自定义图形界面浏览器-Tomcat服务端). 模拟IE 的请求
- windows消息机制详解(转载)
- Educational Codeforces Round 2 600C Make Palindrome(脑洞)
- Objective-C新特性__nonnull和__nullable
- Git 常用命令大全
- Docker到底是什么?为什么它这么火!
- 设计模式读书笔记-----命令模式