指令模式關注動作本身,通過将動作封裝成對象實作調用者和底層實作相分離。調用者隻需要簡單的下達指令,然後等待指令完成即可,對底層發生了什麼完全不知情。
指令模式關注動作本身,通過将動作封裝成對象實作調用者和底層實作相分離。調用者隻需要簡單的下達指令,然後等待指令完成即可,對底層發生了什麼完全不知情。關于指令模式一個很直覺的例子就是點餐:當我們點餐時,我們隻用關心将選好的菜品下單,然後等待送餐即可,我們不關心飯菜是怎麼做的,不關心廚師是男是女。
下面通過一個萬能遙控器的例子進一步認識指令模式。
步入物聯網時代,很多家電都可以實作遠端控制,我們想看電視,聽音樂,打掃房間,隻需要按一下遙控器上對應的按鍵,相應的家電就會自動工作。那麼這樣的一款遙控器要怎樣實作呢?現在的場景是,遙控器上的多個按鈕對應多個家電,每個家電都有“開”、“關”兩個指令。當然,最重要的地方在于,遙控器還必須要能夠友善擴充,以後購置新的家電時,隻要加一些按鈕就可以了。
首先定義指令接口,為簡單起見,指令接口裡面隻有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就是家電。
以上就是指令模式的簡單應用,它允許我們将動作封裝成指令對象,然後就可以随心所欲地存儲、傳遞和調用它們了。通過指令對象實作調用者和執行者解耦,兩者之間通過指令對象間接地進行溝通。