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
咱們能夠很輕鬆地利用組合模式加入宏命令,還有,正如以上代碼所示,命令模式的不足之處就是咱們須要維護大量的具體命令類。