1. 程式人生 > >設計模式 - 命令模式詳解及其在JdbcTemplate中的應用

設計模式 - 命令模式詳解及其在JdbcTemplate中的應用

# 基本介紹 > 在軟體設計中,我們經常需要向某些物件傳送一些請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需要在程式執行時指定具體的請求接收者即可,此時,可以使用命令模式來設計,使得請求傳送者與請求接收者消除彼此之間的耦合,讓物件之間的呼叫關係更加靈活。 命令模式(Command Pattern)可以對傳送者和接收者完全解耦,傳送者與接收者之間沒有直接引用關係,傳送請求的物件只需要知道如何傳送請求,而不必知道如何完成請求。 命令模式將一個請求封裝為一個物件,從而使我們可用不同的請求對客戶進行引數化;對請求排隊或者記錄請求日誌,以及支援可撤銷的操作。 # 模式結構 ![](https://gitee.com/songjilong/FigureBed/raw/master/img/20200425234945.png) - Invoker:呼叫者,傳送命令 - Receiver:接收者,接收命令 - Command:抽象命令類,定義了所有的命令 - ConcreteCommand:具體命令類,呼叫接收者的操作 # 舉例說明 > 現有許多家電(電燈、電視機、空調....),每個家電都有自己的控制裝置,如果需要控制它們,需要逐個開啟、逐個關閉,這時候,如果有一個萬能遙控器(如下如所示),操作不同的家電只需要按對應的按鈕即可,如何使用命令模式實現?
1、建立電燈的命令接收者 ```java public class LightReceiver { public void on() { System.out.println("電燈打開了"); } public void off() { System.out.println("電燈關閉了"); } } ``` 2、建立抽象的命令介面 ```java public interface Command { /** * 執行命令 */ void execute(); /** * 撤銷命令 */ void undo(); } ``` 3、建立電燈的開啟、關閉命令類,實現命令介面 ```java public class LightOnCommand implements Command { private LightReceiver lightReceiver; public LightOnCommand(LightReceiver lightReceiver) { this.lightReceiver = lightReceiver; } @Override public void execute() { lightReceiver.on(); } @Override public void undo() { lightReceiver.off(); } } ``` ```java public class LightOffCommand implements Command { private LightReceiver lightReceiver; public LightOffCommand(LightReceiver lightReceiver) { this.lightReceiver = lightReceiver; } @Override public void execute() { lightReceiver.off(); } @Override public void undo() { lightReceiver.on(); } } ``` 4、建立空的命令類,用於初始化按鈕 ```java public class NullCommand implements Command { @Override public void execute() { } @Override public void undo() { } } ``` 5、建立命令呼叫者 ```java public class RemoteController { /** * 操作物件的個數 */ private static final int COUNT = 5; /** * 開啟命令組 */ Command[] onCommands; /** * 關閉命令組 */ Command[] offCommands; /** * 執行撤銷的命令 */ Command undoCommand; /** * 初始化 */ public RemoteController() { onCommands = new Command[COUNT]; offCommands = new Command[COUNT]; for (int i = 0; i < COUNT; i++) { onCommands[i] = new NullCommand(); offCommands[i] = new NullCommand(); } } /** * 設定按鈕 */ public void setCommand(int no, Command onCommand, Command offCommand) { onCommands[no] = onCommand; offCommands[no] = offCommand; } /** * 按下開按鈕 */ public void pressOnButton(int no) { onCommands[no].execute(); //記錄按鈕,以便撤銷 undoCommand = onCommands[no]; } /** * 按下關按鈕 */ public void pressOffButton(int no) { offCommands[no].execute(); //記錄按鈕,以便撤銷 undoCommand = offCommands[no]; } /** * 按下撤銷按鈕 */ public void pressUndoButton(int no) { if (undoCommand != null) { undoCommand.undo(); } } } ``` 6、測試類 ```java public class Client { @Test public void testLight() { //建立命令接收者 LightReceiver lightReceiver = new LightReceiver(); //建立電燈的一組操作(開和關) LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver); LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver); //建立命令呼叫者 RemoteController remoteController = new RemoteController(); //設定命令 remoteController.setCommand(0, lightOnCommand, lightOffCommand); //執行命令 System.out.println("----按下開燈按鈕----"); remoteController.pressOnButton(0); System.out.println("----按下關燈按鈕----"); remoteController.pressOffButton(0); System.out.println("----按下撤銷按鈕----"); remoteController.pressUndoButton(0); } } ``` 7、執行結果 ``` ----按下開燈按鈕---- 電燈打開了 ----按下關燈按鈕---- 電燈關閉了 ----按下撤銷按鈕---- 電燈打開了 ``` 8、如果再新增一個電視機,不需要改動任何已有的程式碼,新增 `TvReceiver`、`TvOnCommand`、`TvOffCommand` 這幾個類即可。 # 模式分析 **