設計模式之命令模式


1.智能生活項目需求

看一個具體的需求

 我們買了一套智能家電,有照明燈、風扇、冰箱、洗衣機,我們只要在手機上安裝 app 就可以控制對這些家電工作。

這些智能家電來自不同的廠家,我們不想針對每一種家電都安裝一個 App,分別控制,我們希望只要一個 app 就可以控制全部智能家電。

要實現一個 app 控制所有智能家電的需要,則每個智能家電廠家都要提供一個統一的接口給 app 調用,這時 就可以考慮使用命令模式。

命令模式可將“動作的請求者”從“動作的執行者”對象中解耦出來.

在我們的例子中,動作的請求者是手機 app,動作的執行者是每個廠商的一個家電產品

2  命令模式基本介紹

命令模式(Command Pattern):在軟件設計中,我們經常需要向某些對象發送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程序運行時指定具體的請求接收者即可,此時,可以使用命令模式來進行設計 命名模式使得請求發送者與請求接收者消除彼此之間的耦合,讓對象之間的調用關系更加靈活,實現解耦。

在命名模式中,會將一個請求封裝為一個對象,以便使用不同參數來表示不同的請求(即命名),同時命令模式也支持可撤銷的操作。

 通俗易懂的理解:將軍發布命令,士兵去執行。其中有幾個角色:將軍(命令發布者)、士兵(命令的具體執行者)、命令(連接將軍和士兵)。

Invoker 是調用者(將軍),Receiver 是被調用者(士兵),MyCommand 是命令,實現了 Command 接口,持有接收對象。

命令模式的原理類圖

對原理類圖的說明-即(命名模式的角色及職責)

Invoker  是調用者角色

Command: 是命令角色,需要執行的所有命令都在這里,可以是接口或抽象類

Receiver:  接受者角色,知道如何實施和執行一個請求相關的操作

ConcreteCommand:  將一個接受者對象與一個動作綁定,調用接受者相應的操作,實現 execute

3 命令模式解決智能生活項目

應用實例要求

編寫程序,使用命令模式 完成前面的智能家電項目

思路分析和圖解:

代碼實現

1
2
3
4
5
6
7
8
9
10
11
//創建命令接口
 
public  interface  Command {
     
     //執行動作(操作)
     public  void  execute();
 
     //撤銷動作(操作)
     public  void  undo();
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public  class  LightOffCommand  implements  Command {
     // 聚合 LightReceiver
     LightReceive light;
 
     // 構造器
     public  LightOffCommand(LightReceiver light) {
         super ();
         this .light = light;
 
     }
 
     @Override
 
     public  void  execute() {
 
         //調用接收者的方法
         light.off();
 
     }
 
     @Override
 
     public  void  undo() {
 
         // 調用接收者的方法
         light.on();
 
     }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public  class  LightOnCommand  implements  Command {
 
     //聚合 LightReceiver
     LightReceiver light;
 
     //構造器
     public  LightOnCommand(LightReceiver light) {
         super ();
 
         this .light = light;
 
     }
 
     @Override
     public  void  execute() {
 
         // 調用接收者的方法
         light.on();
 
     }
 
     @Override
     public  void  undo() {
 
         //調用接收者的方法
         light.off();
 
     }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 
  沒有任何命令,即空執行: 用於初始化每個按鈕,  當調用空命令時,對象什么都不做
 
  其實,這樣是一種設計模式, 可以省掉對空判斷
 
  @author Administrator
 
  */
 
public  class  NoCommand  implements  Command {
 
     @Override
     public  void  execute() {
 
     }
 
     @Override
     public  void  undo() {
 
     }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public  class  LightReceiver {
 
     public  void  on() {
 
         System.out.println( "  電燈打開了.. " );
 
     }
 
     public  void  off() {
 
         System.out.println( "  電燈關閉了.. " );
 
     }
 
}

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public  class  RemoteController {
 
     // 開 按鈕的命令數組
     Command[] onCommands;
     Command[] offCommands;
     //    執行撤銷的命令
     Command undoCommand;
     // 構造器,完成對按鈕初始化
 
     public  RemoteController() {
 
         onCommands =  new  Command[ 5 ];
         offCommands =  new  Command[ 5 ];
 
         for  ( int  i =  0 ; i <  5 ; i++) {
             onCommands[i] =  new  NoCommand();
             offCommands[i] =  new  NoCommand();
 
         }
 
     }
 
     // 給我們的按鈕設置你需要的命令
     public  void  setCommand( int  no, Command onCommand, Command offCommand) {
         onCommands[no] = onCommand;
         offCommands[no] = offCommand;
 
     }
 
     // 按下開按鈕
     public  void  onButtonWasPushed( int  no) {
         // no 0 找到你按下的開的按鈕,並調用對應方法
         onCommands[no].execute();
         //        記錄這次的操作,用於撤銷
         undoCommand = onCommands[no];
 
     }
 
     // 按下開按鈕
     public  void  offButtonWasPushed( int  no) {
         // no 0找到你按下的關的按鈕,並調用對應方法
         offCommands[no].execute();
         // 記錄這次的操作,用於撤銷
         undoCommand = offCommands[no];
     }
 
     // 按下撤銷按鈕
     public  void  undoButtonWasPushed() {
         undoCommand.undo();
     }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public  class  Client {
 
     public  static  void  main(String[] args) {
 
         //使用命令設計模式,完成通過遙控器,對電燈的操作
 
         //創建電燈的對象(接受者)
         LightReceiver lightReceiver =  new  LightReceiver();
 
         //創建電燈相關的開關命令
         LightOnCommand lightOnCommand =  new  LightOnCommand(lightReceiver);
 
         LightOffCommand lightOffCommand =  new  LightOffCommand(lightReceiver);
 
         //需要一個遙控器
         RemoteController remoteController =  new  RemoteController();
 
         //給我們的遙控器設置命令, 比如 no = 0 是電燈的開和關的操作
         remoteController.setCommand( 0 , lightOnCommand, lightOffCommand);
 
         System.out.println( "--------   按下燈的開按鈕    -----------" );
         remoteController.onButtonWasPushed( 0 );
         System.out.println( "--------   按下燈的關按鈕    -----------" );
         remoteController.offButtonWasPushed( 0 );
         System.out.println( "--------   按下撤銷按鈕-----------  " );
         remoteController.undoButtonWasPushed();
 
         System.out.println( "=========使用遙控器操作電視機==========" );
 
         TVReceiver tvReceiver =  new  TVReceiver();
 
         TVOffCommand tvOffCommand =  new  TVOffCommand(tvReceiver);
 
         TVOnCommand tvOnCommand =  new  TVOnCommand(tvReceiver);
 
         //給我們的遙控器設置命令, 比如 no = 1 是電視機的開和關的操作
         remoteController.setCommand( 1 , tvOnCommand, tvOffCommand);
 
         System.out.println( "--------   按下電視機的開按鈕  -----------" );
         remoteController.onButtonWasPushed( 1 );
         System.out.println( "--------   按下電視機的關按鈕  -----------" );
         remoteController.offButtonWasPushed( 1 );
         System.out.println( "--------   按下撤銷按鈕-----------  " );
         remoteController.undoButtonWasPushed();
 
     }
 
}


免責聲明!

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



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