命令模式


命令模式關注動作本身,通過將動作封裝成對象實現調用者和底層實現相分離。調用者只需要簡單的下達命令,然后等待命令完成即可,對底層發生了什么完全不知情。關於命令模式一個很直觀的例子就是點餐:當我們點餐時,我們只用關心將選好的菜品下單,然后等待送餐即可,我們不關心飯菜是怎么做的,不關心廚師是男是女。

下面通過一個萬能遙控器的例子進一步認識命令模式。

步入物聯網時代,很多家電都可以實現遠程控制,我們想看電視,聽音樂,打掃房間,只需要按一下遙控器上對應的按鍵,相應的家電就會自動工作。那么這樣的一款遙控器要怎樣實現呢?現在的場景是,遙控器上的多個按鈕對應多個家電,每個家電都有“開”、“關”兩個命令。當然,最重要的地方在於,遙控器還必須要能夠方便擴展,以后購置新的家電時,只要加一些按鈕就可以了。

首先定義命令接口,為簡單起見,命令接口里面只有execute方法,因為命令就是要被執行的:

1 public interface Command {
2   void execute();
3 }

遙控器上的每一個按鈕都是一個命令,對應不同的電器,所以命令應該有很多種具體類型,假設目前有燈泡、電視、音箱三種家電,電器的定義如下:

 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 }

每種電器都有“開”、“關”兩個具體命令,定義如下:

 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類家電,實際上完全可以對接任意的家電。現在就需要寫個測試類看看遙控器是否正常工作:

 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 }

輸出如下:

打開電燈。。。
關閉電燈。。。
打開電視。。。
關閉電視。。。
打開音箱。。。
關閉音箱。。。

遙控器看起來一起順利。對以上的代碼進行整理,可以得出命令模式的類圖如下。

 

遙控器對應Client,各種家電的開關命令對應ConcreteCommand,Receiver就是家電。

以上就是命令模式的簡單應用,它允許我們將動作封裝成命令對象,然后就可以隨心所欲地存儲、傳遞和調用它們了。通過命令對象實現調用者和執行者解耦,兩者之間通過命令對象間接地進行溝通。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM