參考
- 《設計模式:可複用面向對象軟件的基礎 》5.2 Command 命令 對象行爲型模式
- 《Android源碼設計模式解析與實戰》第11章 讓程序暢通執行–命令模式
意圖
將一個請求封裝爲一個對象,從而使你可用不同地請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷地操作。
適用場景
- 需要抽象出待執行地動作,然後以參數地形式提供出來,類似於過程設計中的回調機制,命令模式正是回調機制的一個面向對象的替代品
- 在不同的時刻指定、排列和執行請求。一個命令對象可以有與初始請求無關的生存期。
- 需要支持取消操作。
- 支持修改日誌功能,這樣當系統崩潰時,這些修改可以被重做一遍。
- 需要支持事物操作。
結構
- Reicever 接收者角色,負責具體執行一個請求,任何一個類都可以成爲一個接收者,而在接收者類中封裝具體操作邏輯的方法我們稱爲行動方法(action)
- Command 命令角色 定義所有具體命令類的抽象接口
- ConcreteCommand 具體命令角色,實現了Command接口,在excute方法中調用接收者角色的相關方法,在接收者和命令執行的具體行爲之間加以弱耦合。execute方法成爲執行方法(excute)
- Invoker 請求者角色,負責調用命令對象執行具體的請求,相關的方法我們成爲行動方法(action)
- Client 客戶端角色
執行流程
代碼就略了
優點
更弱的耦合性,更靈活的控制性以及更好的擴展性
缺點
類膨脹,大量衍生類的創建。
例子1 操縱俄羅斯方塊變換
描述
大家小時候都玩過俄羅斯方塊,遊戲中有4個按鈕,分別是兩個左右移動的按鈕,一個快速落下的按鈕,一個變化方塊形狀的按鈕。所以四個按鈕就相當於請求者,執行具體按鈕命令的邏輯方法塊可以看作命令角色。
結構
代碼實現
/**
* 命令的接收者,負責具體執行請求
* @author newtrekWang
* @email [email protected]
* @time 2018/8/20 23:35
*/
public class TetrisMachine {
public void toLeft(){
System.out.println("向左");
}
public void toRigth(){
System.out.println("向右");
}
public void fastToBottom(){
System.out.println("快速向下");
}
public void transform(){
System.out.println("變換形狀");
}
}
/**
* 命令抽象
* @author newtrekWang
* @email [email protected]
* @time 2018/8/20 23:37
*/
public interface Command {
/**
* 執行命令
*/
void execute();
}
/**
* 向左命令
* @author newtrekWang
* @email [email protected]
* @time 2018/8/20 23:39
*/
public class LeftCommand implements Command {
private TetrisMachine tetrisMachine;
public LeftCommand(TetrisMachine tetrisMachine) {
this.tetrisMachine = tetrisMachine;
}
@Override
public void execute() {
tetrisMachine.toLeft();
}
}
/**
* 向右命令
* @author newtrekWang
* @email [email protected]
* @time 2018/8/20 23:39
*/
public class RightCommand implements Command {
private TetrisMachine tetrisMachine;
public RightCommand(TetrisMachine tetrisMachine) {
this.tetrisMachine = tetrisMachine;
}
@Override
public void execute() {
tetrisMachine.toRigth();
}
}
/**
* 快速向下命令
* @author newtrekWang
* @email [email protected]
* @time 2018/8/20 23:39
*/
public class FallCommand implements Command {
private TetrisMachine tetrisMachine;
public FallCommand(TetrisMachine tetrisMachine) {
this.tetrisMachine = tetrisMachine;
}
@Override
public void execute() {
tetrisMachine.fastToBottom();
}
}
/**
* 變換形狀命令
* @author newtrekWang
* @email [email protected]
* @time 2018/8/20 23:39
*/
public class TransformCommand implements Command {
private TetrisMachine tetrisMachine;
public TransformCommand(TetrisMachine tetrisMachine) {
this.tetrisMachine = tetrisMachine;
}
@Override
public void execute() {
tetrisMachine.transform();
}
}
public static void main(String[] args){
TetrisMachine tetrisMachine = new TetrisMachine();
LeftCommand leftCommand = new LeftCommand(tetrisMachine);
RightCommand rightCommand = new RightCommand(tetrisMachine);
FallCommand fallCommand = new FallCommand(tetrisMachine);
TransformCommand transformCommand = new TransformCommand(tetrisMachine);
leftCommand.execute();
leftCommand.execute();
fallCommand.execute();
transformCommand.execute();
rightCommand.execute();
}
執行結果:
向左
向左
快速向下
變換形狀
向右
例子2 Android事件機制中底層邏輯對事件的轉發處理
Android的每一種事件在屏幕上產生後都會經由底層邏輯將其轉換爲一個NotifyArgs對象,NotifyAgs本身並無實現,其實它就相當於一個Command抽象。
例子3 運用命令模式實現Android繪圖板
後更