將一個請求封裝爲一個對象,從而使你可以用不同的請求對客戶進行參數化,
對請求排隊或記錄請求日誌,以及支持可撤銷的操作。
@@@練習示例:
電腦開機
@@@示例代碼:
\pattern\MainBoardApi.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 主板的接口
*/
public interface MainBoardApi {
/**
* 主板具有能開機的功能
*/
public void open();
/**
* 主板具有實現重啓的功能
*/
public void reset();
}
\pattern\GigaMainBoard.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 技嘉主板類,開機命令的真正實現者,在Command模式中充當Receiver
*/
public class GigaMainBoard implements MainBoardApi {
/**
* 真正的開機命令的實現
*/
public void open() {
System.out.println("技嘉主板現在正在開機,請等候");
System.out.println("接通電源……");
System.out.println("設備檢查……");
System.out.println("裝載系統……");
System.out.println("機器正常運轉起來……");
System.out.println("機器已經正常打開,請操作");
}
/**
* 真正的重新啓動機器命令的實現
*/
public void reset() {
System.out.println("技嘉主板現在正在重啓機器,請等候");
System.out.println("機器已經正常打開,請操作");
}
}
\pattern\Command.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 命令接口,申明執行的操作
*/
public interface Command {
/**
* 執行命令對應的操作
*/
public void execute();
}
\pattern\OpenCommand.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 開機命令的實現,實現Command接口
* 持有開機命令的真正實現,通過調用接收者的方法來實現命令
*/
public class OpenCommand implements Command {
/**
* 持有真正實現命令的接收者——主板對象
*/
private MainBoardApi mainBoard = null;
/**
* 構造方法,傳入主板對象
* @param mainBoard 主板對象
*/
public OpenCommand(MainBoardApi mainBoard) {
this.mainBoard = mainBoard;
}
@Override
public void execute() {
// 對於命令對象,根本不知道如何開機,會轉調主板對象
// 讓主板去完成開機的功能
this.mainBoard.open();
}
}
\pattern\ResetCommand.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 重啓機器命令的實現,實現Command接口
* 持有重啓機器命令的真正實現,通過調用接收者的方法來實現命令
*/
public class ResetCommand implements Command {
/**
* 持有真正實現命令的接收者——主板對象
*/
private MainBoardApi mainBoard = null;
/**
* 構造方法,傳入主板對象
* @param mainBoard 主板對象
*/
public ResetCommand(MainBoardApi mainBoard) {
this.mainBoard = mainBoard;
}
@Override
public void execute() {
// 對於命令對象,根本不知道如何開機,會轉調主板對象
// 讓主板去完成重啓機器的功能
this.mainBoard.reset();
}
}
\pattern\Box.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
/**
* 機箱對象,本身有按鈕,持有按鈕對應的命令對象
*/
public class Box {
/**
* 開機命令對象
*/
private Command openCommand;
/**
* 設置開機命令對象
* @param command 開機命令對象
*/
public void setOpenCommand(Command command) {
this.openCommand = command;
}
/**
* 提供給客戶使用,接收並響應用戶請求,相當於開機按鈕被按下觸發的方法
*/
public void openButtonPressed() {
// 按下按鈕,執行命令
openCommand.execute();
}
private Command resetCommand;
/**
* 設置重啓機器命令對象
* @param command
*/
public void setResetCommand(Command command) {
this.resetCommand = command;
}
/**
* 提供給客戶使用,接收並響應用戶請求,相當於重啓按鈕被按下觸發的方法
*/
public void resetButtonPressed() {
// 按下按鈕,執行命令
resetCommand.execute();
}
}
\pattern\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern;
public class Client {
public static void main(String[] args) {
// 1: 把命令和真正的實現組合起來,相當於在組裝機器
// 把機箱上按鈕的連接線插接到主板上
MainBoardApi mainBoard = new GigaMainBoard();
// 創建開機命令
OpenCommand openCommand = new OpenCommand(mainBoard);
// 創建重啓命令
ResetCommand resetCommand = new ResetCommand(mainBoard);
// 2: 爲機箱上的按鈕設置對應的命令,讓按鈕知道該幹什麼
Box box = new Box();
// 先正確配置,就是開機按鈕對開機命令,重啓按鈕對重啓命令
box.setOpenCommand(openCommand);
box.setResetCommand(resetCommand);
// 3: 然後模擬按下機箱上的按鈕
System.out.println("正確配置下------------------>");
System.out.println(">>>按下開機按鈕:>>>");
box.openButtonPressed();
System.out.println(">>>按下重啓按鈕:>>>");
box.resetButtonPressed();
// 然後來錯誤配置一回,反正是進行參數化配置
// 就是開機按鈕對重啓命令,重啓按鈕對開機命令
box.setOpenCommand(resetCommand);
box.setResetCommand(openCommand);
System.out.println("錯誤配置下------------------>");
System.out.println(">>>按下開機按鈕:>>>");
box.openButtonPressed();
System.out.println(">>>按下重啓按鈕:>>>");
box.resetButtonPressed();
}
}
@@@模式的實現:
1) 命令模式的關鍵之處就是把請求封裝成爲對象,也就是命令對象,並定義了一個統一操作的接口;
2) 可實現成參數化的命令模式;
3) 可實現(補償式/反操作式)可撤銷的操作;
4) 可實現宏命令(命令集);
5) 可實現隊列請求;
6) 可實現日誌請求;
@@@模式的優點:
1) 更鬆散的耦合;
2) 更動態的控制;
3) 很自然的複合命令;
4) 更好地擴展性;
@@@模式的缺點:
NA
@@@模式的本質:
封裝請求
@@@模式體現的設計原則:
NA