命令模式(Command)

@@@模式定義:
將一個請求封裝爲一個對象,從而使你可以用不同的請求對客戶進行參數化,
對請求排隊或記錄請求日誌,以及支持可撤銷的操作。


@@@練習示例: 
電腦開機


@@@示例代碼:
\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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章