1、命令模式定义
命令你们都不会陌生,那么在开始命令模式以前,能够想象一下生活中的命令模式的特色:app
如老板命令你完成一个OA项目是一个命令,接着看看其特色:eclipse
一、在上面的命令中,命令的执行者确定是聪明的你了。具体的执行方法,多是经过vs实现,或者是经过eclipse实现,由此看来:命令要有个命令的执行者,还要有个命令的执行方法。测试
二、命令的发出者很明显是老板,老板还有个发出方法,多是经过电话给你说,也可能给你邮件给你说,也多是经过开会给你说。因此命令的发出者要有一个命令,还要有个发出的方法。this
三、最后看看命令,命令有个名字,命令的确定要执行。并且命令是在boss给你发出通知后执行的。spa
接下来看看命令模式的定义:日志
命令模式:将请求封装成对象,以便使用不一样的请求、日志、队列等来参数化其余对象。命令模式也支持撤销操做。对象
2、问题描述
使用命令模式实现遥控器,遥控器上的不一样按钮控制电灯的开关及亮度、天花板风扇的开关及转速等,支持撤销。具体按钮:开灯/关灯按钮、暗光开/关按钮、风扇高速/中速/低速/关按钮、撤销按钮。遥控器以下图所示:队列

遥控器担当请求者(或称为调用者)的角色,用RemoteControlWithUndo类实现,其内有Command[]类型的属性onCommands和offCommands表示对应的一组开关,Command类型的属性undoCommand记录最后执行的命令用于命令的撤销。遥控器上有7组开关按钮和一个撤销按钮。每一个按钮对应一个具体命令,说明以下:ip

3、类图

4、代码实现
1.命令角色:Command
- public interface Command {
- public void execute();
- public void undo();//实现撤销
- }
2.接收者角色:Light、CeilingFan
(1)Light电灯:rem
- 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更好),什么事也不作
- 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();
- }
- }
运行结果:
- Light is dimmed to 75%
- Living Room ceiling fan is on medium
- Living Room ceiling fan is on high
- Living Room ceiling fan is off
- Living Room ceiling fan is on high
咱们能够很轻松地利用组合模式加入宏命令,还有,正如以上代码所示,命令模式的不足之处就是咱们须要维护大量的具体命令类。