您的位置:首页 > 其它

命令模式

2016-01-22 10:34 323 查看
定义:命令模式将请求封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也可支持可撤销的操作。

类图:



要点:

命令模式将发出的请求对象和执行的请求对象解耦。在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接受者一个或一组请求。

调用者通过调用命令对象的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();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: