我們日常的開發就很好地體現出了命令模式,比如:領導将開發任務指派給程序員去完成。其中領導就是“命令的發布者(調用者)”,程序員就是“命令的具體執行者(接收者)”,這個指派的動作就是“具體的命令”。命令将調用者和接收者進行連接,從而完成開發任務,這一套流程就可以看作是命令模式的執行原理。
命令模式使得請求的發送者與請求的執行者之間消除耦合,讓對象之間的調用關系更加靈活。在命令模式中,會将一個命令封裝成一個對象,同時命令模式也支持可撤銷的操作。
命令模式UML類圖
UML類圖講解
Invoker:調用者角色。Command:抽象命令角色,封裝了所有需要執行的命令,可以是抽象類或接口。Receiver:接收者角色,具體執行命令的類。ConcreteCommand:具體命令角色,實現了Command類,并聚合了Receiver類。該類的作用是将一個接收者對象與一個命令進行綁定。
案例講解通過上面的介紹相信大家對命令模式模式有了一個簡單的認識,下面讓我們通過一個案例來加深對該模式的理解。
案例:實現通過遙控器開關電視以及撤銷上一次操作的功能。
命令接口 => 對應抽象命令角色
public interface Command { // 執行操作 void execute(); // 撤銷操作 void undo(); }
電視 => 對應接收者角色
public class TVReceiver { public void on() { System.out.println("電視機打開了。"); } public void off() { System.out.println("電視機關閉了。"); } }
具體命令實現類
/** * 開電視 */ public class TVOnCommand implements Command { // 聚合TVReceiver private TVReceiver tv; public TVOnCommand(TVReceiver tv) { this.tv = tv; } @Override public void execute() { // 執行打開電視機命令 this.tv.on(); } @Override public void undo() { // 執行關閉電視機命令,因為打開電視對應的就是關閉。 this.tv.off(); } } /** * 關閉電視 */ public class TVOffCommand implements Command { // 聚合TVReceiver private TVReceiver tv; public TVOffCommand(TVReceiver tv) { this.tv = tv; } @Override public void execute() { // 執行關閉電視機命令 this.tv.off(); } @Override public void undo() { // 執行打開電視機命令,因為關閉電視機對應的就是打開。 this.tv.on(); } } /** * 空命令 * 該類默認實現Command接口,不執行任何命令。添加該類的作用是 * 為了省略執行操作時對空的判斷。 */ public class NoCommand implements Command { @Override public void execute() { } @Override public void undo() { } }
遙控器 => 對應調用者角色
public class RemoteController { // 開按鈕的命令 private Command onCommand = new NoCommand(); // 關按鈕的命令 private Command offCommand = new NoCommand(); // 執行撤銷的命令 private Command undoCommand = new NoCommand(); // 給按鈕設置相關命令 public void setCommand(Command onCommand, Command offCommand) { this.onCommand = onCommand; this.offCommand = offCommand; } // 按下打開按鈕 public void onButtonWasPushed() { this.onCommand.execute(); // 記錄本次操作 this.undoCommand = this.onCommand; } // 按下關閉按鈕 public void offButtonWasPushed() { this.offCommand.execute(); // 記錄本次操作 this.undoCommand = this.offCommand; } // 按下撤銷按鈕 public void undoButtonWasPushed() { this.undoCommand.undo(); } }
客戶端測試類
public class Client { public static void main(String[] args) { // 創建電視機接收者 TVReceiver tvReceiver = new TVReceiver(); // 創建電視機開關命令 TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver); TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver); // 創建遙控器 RemoteController remoteController = new RemoteController(); // 設置命令 remoteController.setCommand(tvOnCommand, tvOffCommand); System.out.println("======按下打開按鈕======"); remoteController.onButtonWasPushed(); System.out.println("======按下關閉按鈕======"); remoteController.offButtonWasPushed(); System.out.println("======撤銷上次操作======"); remoteController.undoButtonWasPushed(); } }
執行結果
總結
優點
1、調用者隻需要調用命令對象的“執行”方法就可以讓接收者工作,而不必知道具體是誰接收的命令,命令是如何被執行的。将發起命令請求的對象和執行命令的對象拆分開從而促使代碼解耦,通過這樣的設計将利于程序的擴展。2、通過添加一個“空命令”來省去判空的操作。3、通過添加撤銷方法可以實現對命令的撤銷重做。
缺點:
造成系統存在過多的具體命令類,增加系統的複雜度。
注意
命令對象負責讓具體的接收者執行指定的操作,它就是連接“請求發起者”和“請求執行者”的橋梁。
今天的分享就到這裡了,如果感覺“菜鳥”寫的文章還不錯,記得點贊加關注呦!你們的支持就是我堅持下去的動力。文章哪裡寫的有問題的也希望大家可以指出,我會虛心受教。
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!