《設計模式》之命令模式

1、命令模式定義

命令你們都不會陌生,那麼在開始命令模式以前,能夠想象一下生活中的命令模式的特色:app

如老闆命令你完成一個OA項目是一個命令,接着看看其特色:eclipse

一、在上面的命令中,命令的執行者確定是聰明的你了。具體的執行方法,多是經過vs實現,或者是經過eclipse實現,由此看來:命令要有個命令的執行者,還要有個命令的執行方法。測試

二、命令的發出者很明顯是老闆,老闆還有個發出方法,多是經過電話給你說,也可能給你郵件給你說,也多是經過開會給你說。因此命令的發出者要有一個命令,還要有個發出的方法。this

三、最後看看命令,命令有個名字,命令的確定要執行。並且命令是在boss給你發出通知後執行的。spa

接下來看看命令模式的定義:日誌

命令模式:將請求封裝成對象,以便使用不一樣的請求、日誌、隊列等來參數化其餘對象。命令模式也支持撤銷操做。對象

2、問題描述

 

     使用命令模式實現遙控器,遙控器上的不一樣按鈕控制電燈的開關及亮度、天花板風扇的開關及轉速等,支持撤銷。具體按鈕:開燈/關燈按鈕、暗光開/關按鈕、風扇高速/中速/低速/關按鈕、撤銷按鈕。遙控器以下圖所示:隊列

     遙控器擔當請求者(或稱爲調用者)的角色,用RemoteControlWithUndo類實現,其內有Command[]類型的屬性onCommands和offCommands表示對應的一組開關,Command類型的屬性undoCommand記錄最後執行的命令用於命令的撤銷。遙控器上有7組開關按鈕和一個撤銷按鈕。每一個按鈕對應一個具體命令,說明以下:ip

3、類圖

4、代碼實現

1.命令角色:Command

  1. public interface Command {  
  2.     public void execute();  
  3.     public void undo();//實現撤銷  
  4. }  

2.接收者角色:Light、CeilingFan

(1)Light電燈:rem

  1. public class Light {  
  2.     String location;  
  3.     int level;//燈光的亮度  
  4.   
  5.     public Light(String location) {  
  6.         this.location = location;  
  7.     }  
  8.   
  9.     public void on() {  
  10.         level = 100;  
  11.         System.out.println("Light is on");  
  12.     }  
  13.   
  14.     public void off() {  
  15.         level = 0;  
  16.         System.out.println("Light is off");  
  17.     }  
  18.     //調整燈光的亮度  
  19.     public void dim(int level) {  
  20.         this.level = level;  
  21.         if (level == 0) {  
  22.             off();  
  23.         }  
  24.         else {  
  25.             System.out.println("Light is dimmed to " + level + "%");  
  26.         }  
  27.     }  
  28.    //獲取燈光的亮度  
  29.     public int getLevel() {  
  30.         return level;  
  31.     }  
  32. }  

(2)CeilingFan風扇:

  1. public class CeilingFan {  
  2.     public static final int HIGH = 3;  
  3.     public static final int MEDIUM = 2;  
  4.     public static final int LOW = 1;  
  5.     public static final int OFF = 0;  
  6.     String location;//例如臥室、客廳的風扇?  
  7.     int speed;  
  8.    
  9.     public CeilingFan(String location) {  
  10.         this.location = location;  
  11.         speed = OFF;  
  12.     }  
  13.     
  14.     public void high() {  
  15.         speed = HIGH;  
  16.         System.out.println(location + " ceiling fan is on high");  
  17.     }   
  18.    
  19.     public void medium() {  
  20.         speed = MEDIUM;  
  21.         System.out.println(location + " ceiling fan is on medium");  
  22.     }  
  23.    
  24.     public void low() {  
  25.         speed = LOW;  
  26.         System.out.println(location + " ceiling fan is on low");  
  27.     }  
  28.     
  29.     public void off() {  
  30.         speed = OFF;  
  31.         System.out.println(location + " ceiling fan is off");  
  32.     }  
  33.     
  34.     public int getSpeed() {  
  35.         return speed;  
  36.     }  
  37. }  

3.具體命令角色:各類命令

(1)NoCommand:空命令,建立遙控器時默認其持有的都是空命令(相比判斷null更好),什麼事也不作

  1. public class NoCommand implements Command {  
  2.     public void execute() { }  
  3.     public void undo() { }  
  4. }  

(2)LightOnCommand:開燈命令

  1. public class LightOnCommand implements Command {  
  2.     Light light;  
  3.     int level;//level用於記錄上次的燈光亮度  
  4.     public LightOnCommand(Light light) {  
  5.         this.light = light;  
  6.     }  
  7.    
  8.     public void execute() {  
  9.         level = light.getLevel();  
  10.         light.on();  
  11.     }  
  12.    
  13.     public void undo() {//將燈光的亮度調到前一次的水平實現撤銷  
  14.         light.dim(level);  
  15.     }  
  16. }  


(3)LightOffCommand:關燈命令

  1. public class LightOffCommand implements Command {  
  2.     Light light;  
  3.     int level;  
  4.     public LightOffCommand(Light light) {  
  5.         this.light = light;  
  6.     }  
  7.    
  8.     public void execute() {  
  9.         level = light.getLevel();  
  10.         light.off();  
  11.     }  
  12.    
  13.     public void undo() {  
  14.         light.dim(level);  
  15.     }  
  16. }  


(4)DimmerLightOnCommand:開啓暗光

  1. public class DimmerLightOnCommand implements Command {  
  2.     Light light;  
  3.     int prevLevel;//記錄之前的燈光亮度,撤銷操做時使用  
  4.   
  5.     public DimmerLightOnCommand(Light light) {  
  6.         this.light = light;  
  7.     }  
  8.   
  9.     public void execute() {  
  10.         prevLevel = light.getLevel();  
  11.         light.dim(75);//將燈光亮度調至75%實現暗光  
  12.     }  
  13.   
  14.     public void undo() {  
  15.         light.dim(prevLevel);  
  16.     }  
  17. }  


(5)DimmerLightOffCommand:關閉暗光

  1. public class DimmerLightOffCommand implements Command {  
  2.     Light light;  
  3.     int prevLevel;  
  4.   
  5.     public DimmerLightOffCommand(Light light) {  
  6.         this.light = light;  
  7.         prevLevel = 100;  
  8.     }  
  9.   
  10.     public void execute() {  
  11.         prevLevel = light.getLevel();  
  12.         light.off();  
  13.     }  
  14.   
  15.     public void undo() {  
  16.         light.dim(prevLevel);  
  17.     }  
  18. }  

(6)CeilingFanHighCommand:風扇高轉速

  1. public class CeilingFanHighCommand implements Command {  
  2.     CeilingFan ceilingFan;  
  3.     int prevSpeed;//記錄之前的轉速,用於撤銷操做(0時表示之前的狀態是:關)  
  4.     
  5.     public CeilingFanHighCommand(CeilingFan ceilingFan) {  
  6.         this.ceilingFan = ceilingFan;  
  7.     }  
  8.    
  9.     public void execute() {  
  10.         prevSpeed = ceilingFan.getSpeed();  
  11.         ceilingFan.high();  
  12.     }  
  13.    
  14.     public void undo() {  
  15.         if (prevSpeed == CeilingFan.HIGH) {  
  16.             ceilingFan.high();  
  17.         } else if (prevSpeed == CeilingFan.MEDIUM) {  
  18.             ceilingFan.medium();  
  19.         } else if (prevSpeed == CeilingFan.LOW) {  
  20.             ceilingFan.low();  
  21.         } else if (prevSpeed == CeilingFan.OFF) {  
  22.             ceilingFan.off();  
  23.         }  
  24.     }  
  25. }  

(7)CeilingFanMediumCommand:風扇中轉速

  1. public class CeilingFanMediumCommand implements Command {  
  2.     CeilingFan ceilingFan;  
  3.     int prevSpeed;  
  4.     
  5.     public CeilingFanMediumCommand(CeilingFan ceilingFan) {  
  6.         this.ceilingFan = ceilingFan;  
  7.     }  
  8.    
  9.     public void execute() {  
  10.         prevSpeed = ceilingFan.getSpeed();  
  11.         ceilingFan.medium();//將行爲的真正執行委託給接收者,此處即ceilingFan風扇對象  
  12.     }  
  13.    
  14.     public void undo() {  
  15.         if (prevSpeed == CeilingFan.HIGH) {  
  16.             ceilingFan.high();  
  17.         } else if (prevSpeed == CeilingFan.MEDIUM) {  
  18.             ceilingFan.medium();  
  19.         } else if (prevSpeed == CeilingFan.LOW) {  
  20.             ceilingFan.low();  
  21.         } else if (prevSpeed == CeilingFan.OFF) {  
  22.             ceilingFan.off();  
  23.         }  
  24.     }  
  25. }  

(8)CeilingFanLowCommand:風扇低轉速

  1. public class CeilingFanLowCommand implements Command {  
  2.     CeilingFan ceilingFan;  
  3.     int prevSpeed;  
  4.     
  5.     public CeilingFanLowCommand(CeilingFan ceilingFan) {  
  6.         this.ceilingFan = ceilingFan;  
  7.     }  
  8.    
  9.     public void execute() {  
  10.         prevSpeed = ceilingFan.getSpeed();  
  11.         ceilingFan.low();  
  12.     }  
  13.    
  14.     public void undo() {  
  15.         if (prevSpeed == CeilingFan.HIGH) {  
  16.             ceilingFan.high();  
  17.         } else if (prevSpeed == CeilingFan.MEDIUM) {  
  18.             ceilingFan.medium();  
  19.         } else if (prevSpeed == CeilingFan.LOW) {  
  20.             ceilingFan.low();  
  21.         } else if (prevSpeed == CeilingFan.OFF) {  
  22.             ceilingFan.off();  
  23.         }  
  24.     }  
  25. }  

(9)CeilingFanOffCommand:關閉風扇

  1. public class CeilingFanOffCommand implements Command {  
  2.     CeilingFan ceilingFan;  
  3.     int prevSpeed;  
  4.     
  5.     public CeilingFanOffCommand(CeilingFan ceilingFan) {  
  6.         this.ceilingFan = ceilingFan;  
  7.     }  
  8.    
  9.     public void execute() {  
  10.         prevSpeed = ceilingFan.getSpeed();  
  11.         ceilingFan.off();  
  12.     }  
  13.    
  14.     public void undo() {  
  15.         if (prevSpeed == CeilingFan.HIGH) {  
  16.             ceilingFan.high();  
  17.         } else if (prevSpeed == CeilingFan.MEDIUM) {  
  18.             ceilingFan.medium();  
  19.         } else if (prevSpeed == CeilingFan.LOW) {  
  20.             ceilingFan.low();  
  21.         } else if (prevSpeed == CeilingFan.OFF) {  
  22.             ceilingFan.off();  
  23.         }  
  24.     }  
  25. }  

4.遙控器類,請求者(或調用者)角色,持有多個Command對象

  1. public class RemoteControlWithUndo {  
  2.     Command[] onCommands;//對應多個開按鈕  
  3.     Command[] offCommands;//對應多個關按鈕  
  4.     Command undoCommand;//對應撤銷按鈕  
  5.    
  6.     public RemoteControlWithUndo() {  
  7.         onCommands = new Command[7];  
  8.         offCommands = new Command[7];  
  9.    
  10.         Command noCommand = new NoCommand();  
  11.         for(int i=0;i<7;i++) {  
  12.             onCommands[i] = noCommand;//默認賦值爲空命令,什麼事也不作  
  13.             offCommands[i] = noCommand;  
  14.         }  
  15.         undoCommand = noCommand;  
  16.     }  
  17.     
  18.     public void setCommand(int slot, Command onCommand, Command offCommand) { 
  19.         onCommands[slot] = onCommand;  
  20.         offCommands[slot] = offCommand;  
  21.     }  
  22.    
  23.     //當編號爲第slot的開On按鈕按下時執行命令  
  24.     public void onButtonWasPushed(int slot) {  
  25.         onCommands[slot].execute();  
  26.         undoCommand = onCommands[slot];//記錄最後執行的命令  
  27.     }  
  28.    
  29.     public void offButtonWasPushed(int slot) {  
  30.         offCommands[slot].execute();  
  31.         undoCommand = offCommands[slot];  
  32.     }  
  33.    
  34.     public void undoButtonWasPushed() {  
  35.         undoCommand.undo();  
  36.     }  
  37.     
  38.     public String toString() {  
  39.         StringBuffer stringBuff = new StringBuffer();  
  40.         stringBuff.append("\n------ Remote Control -------\n");  
  41.         for (int i = 0; i < onCommands.length; i++) {  
  42.             stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()  
  43.                 + "    " + offCommands[i].getClass().getName() + "\n");  
  44.         }  
  45.           
  46.         stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");  
  47.         return stringBuff.toString();  
  48.     }  
  49. }  

5.測試

  1. public class RemoteLoader {  
  2.    
  3.     public static void main(String[] args) {  
  4.         RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();  
  5.    
  6.         Light livingRoomLight = new Light("Living Room");  
  7.    
  8.         LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);  
  9.         LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);   
  10.         DimmerLightOnCommand dimmerLightOnCommand=new DimmerLightOnCommand(livingRoomLight);  
  11.         DimmerLightOffCommand dimmerLightOffCommand=new DimmerLightOffCommand(livingRoomLight);  
  12.           
  13.         CeilingFan ceilingFan = new CeilingFan("Living Room");  
  14.      
  15.         CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);  
  16.         CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);  
  17.         CeilingFanLowCommand ceilingFanLow =new CeilingFanLowCommand(ceilingFan);  
  18.         CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);  
  19.     
  20.         remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);  
  21.         remoteControl.setCommand(1, dimmerLightOnCommand, dimmerLightOffCommand);  
  22.         remoteControl.setCommand(2, ceilingFanHigh, ceilingFanOff);  
  23.         remoteControl.setCommand(3, ceilingFanMedium, ceilingFanOff);  
  24.         remoteControl.setCommand(4, ceilingFanLow, ceilingFanOff);  
  25.   
  26.         remoteControl.onButtonWasPushed(1);  
  27.         remoteControl.onButtonWasPushed(3);  
  28.         remoteControl.onButtonWasPushed(2);  
  29.         remoteControl.offButtonWasPushed(3);  
  30.           
  31.         remoteControl.undoButtonWasPushed();  
  32.     }  
  33. }  


運行結果:

  1. Light is dimmed to 75%  
  2. Living Room ceiling fan is on medium  
  3. Living Room ceiling fan is on high  
  4. Living Room ceiling fan is off  
  5. Living Room ceiling fan is on high  

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

相關文章
相關標籤/搜索