命令模式關注動做自己,經過將動做封裝成對象實現調用者和底層實現相分離。調用者只須要簡單的下達命令,而後等待命令完成便可,對底層發生了什麼徹底不知情。關於命令模式一個很直觀的例子就是點餐:當咱們點餐時,咱們只用關心將選好的菜品下單,而後等待送餐便可,咱們不關心飯菜是怎麼作的,不關心廚師是男是女。ide
下面經過一個萬能遙控器的例子進一步認識命令模式。測試
步入物聯網時代,不少家電均可以實現遠程控制,咱們想看電視,聽音樂,打掃房間,只須要按一下遙控器上對應的按鍵,相應的家電就會自動工做。那麼這樣的一款遙控器要怎樣實現呢?如今的場景是,遙控器上的多個按鈕對應多個家電,每一個家電都有「開」、「關」兩個命令。固然,最重要的地方在於,遙控器還必需要可以方便擴展,之後購置新的家電時,只要加一些按鈕就能夠了。this
首先定義命令接口,爲簡單起見,命令接口裏面只有execute方法,由於命令就是要被執行的:spa
1 public interface Command { 2 void execute(); 3 }
遙控器上的每個按鈕都是一個命令,對應不一樣的電器,因此命令應該有不少種具體類型,假設目前有燈泡、電視、音箱三種家電,電器的定義以下:3d
1 // 燈泡 2 public class Light { 3 public void on(){ 4 System.out.println("打開電燈。。。"); 5 } 6 7 public void off(){ 8 System.out.println("關閉電燈。。。"); 9 } 10 } 11 12 // 電視 13 public class TV { 14 public void on(){ 15 System.out.println("打開電視。。。"); 16 } 17 18 public void off(){ 19 System.out.println("關閉電視。。。"); 20 } 21 } 22 23 // 音箱 24 public class LoudspeakerBox { 25 public void on(){ 26 System.out.println("打開音箱。。。"); 27 } 28 29 public void off(){ 30 System.out.println("關閉音箱。。。"); 31 } 32 }
每種電器都有「開」、「關」兩個具體命令,定義以下:code
1 // 開燈命令 2 public class LightOnCommand implements Command{ 3 Light light; 4 5 public LightOnCommand(Light light){ 6 this.light = light; 7 } 8 9 @Override 10 public void execute() { 11 light.on(); 12 } 13 } 14 15 // 關燈命令 16 public class LightOffCommand implements Command{ 17 Light light; 18 19 public LightOffCommand(Light light){ 20 this.light = light; 21 } 22 23 @Override 24 public void execute() { 25 light.off(); 26 } 27 } 28 29 // 電視和音箱的開關命令與此類型,略去 30 ...
如今能夠看看遙控器的樣子了:對象
1 // 遙控器 2 public class RemoteController { 3 Command[] onCommands; 4 Command[] offCommands; 5 6 public RemoteController(int commandSize){ 7 this.onCommands = new Command[commandSize]; 8 this.offCommands = new Command[commandSize]; 9 } 10 11 public void setCommand(int i, Command onCommand, Command offCommand){ 12 onCommands[i] = onCommand; 13 offCommands[i] = offCommand; 14 } 15 16 // 按下開按鈕 17 public void onButtonPressed(int i){ 18 onCommands[i].execute(); 19 } 20 21 // 按下關按鈕 22 public void offButtonPressed(int i){ 23 offCommands[i].execute(); 24 } 25 }
遙控器針對每一種家電設置了兩個開關,按下對應的家電的對應開關,會觸發相應的動做。這裏只對接了3類家電,實際上徹底能夠對接任意的家電。如今就須要寫個測試類看看遙控器是否正常工做:blog
1 public class RemoteControllerTest { 2 public static void main(String[] args){ 3 Light light = new Light(); 4 TV tv = new TV(); 5 LoudspeakerBox loudspeakerBox = new LoudspeakerBox(); 6 Command lightOn = new LightOnCommand(light); 7 Command lightOff = new LightOffCommand(light); 8 Command TVOn = new TVOnCommand(tv); 9 Command TVOff = new TVOffCommand(tv); 10 Command LoudspeakerBoxOn = new LoudspeakerBoxOnCommand(loudspeakerBox); 11 Command LoudspeakerBoxOff = new LoudspeakerBoxOffCommand(loudspeakerBox); 12 13 RemoteController remoteController = new RemoteController(3); 14 remoteController.setCommand(0, lightOn, lightOff); 15 remoteController.setCommand(1, TVOn, TVOff); 16 remoteController.setCommand(2, LoudspeakerBoxOn, LoudspeakerBoxOff); 17 18 remoteController.onButtonPressed(0); 19 remoteController.offButtonPressed(0); 20 remoteController.onButtonPressed(1); 21 remoteController.offButtonPressed(1); 22 remoteController.onButtonPressed(2); 23 remoteController.offButtonPressed(2); 24 } 25 }
輸出以下:接口
打開電燈。。。
關閉電燈。。。
打開電視。。。
關閉電視。。。
打開音箱。。。
關閉音箱。。。
遙控器看起來一塊兒順利。對以上的代碼進行整理,能夠得出命令模式的類圖以下。rem
遙控器對應Client,各類家電的開關命令對應ConcreteCommand,Receiver就是家電。
以上就是命令模式的簡單應用,它容許咱們將動做封裝成命令對象,而後就能夠爲所欲爲地存儲、傳遞和調用它們了。經過命令對象實現調用者和執行者解耦,二者之間經過命令對象間接地進行溝通。