5 分鐘閱讀

命令模式

命令模式是一種封裝的用法
具體上封裝的東西是方法

例如 媽媽請你去打掃,那嬤嬤不用知道妳具體上怎麼打掃
寄送包裹,中間發生什麼事情不知道,最後就是會到達目的地
按下遙控器,不知道具體怎麼動作,重點是電視就是會開機

解析命令的組成

以去郵局寄包裹的流程來說明

  1. 要先填寄送單
  2. 櫃員接受單子
  3. 郵差送信

以媽媽請我們打掃的流程

  1. 媽媽說要打掃哪裡
  2. 你接收訊息
  3. 找一個時間去打掃

以命令模式來解釋

  • Client 客戶,產生命令的物件
  • Command 命令,被Client產生的物件,包含Receiver與執行的動作
  • Invoker 呼叫者,實際上呼叫命令的物件,可以設定要執行的command
  • Receiver 接收者,實際上執行動作的物件
  • Execute 執行的動作,Command的方法,Receiver要執行的動作會封裝在這個地方

以打掃來想像來理解的話
媽媽在這邊就是Client,依照她的Command命令於是就產生
Command裡面包含Receiver就是你與要打掃的動作
媽媽也身兼Invoker呼叫者,把她剛剛想好的Command設定好
然後她就喊一聲趕快去掃(Command.execute())
被封裝在裡面的你(Receiver),就要乖乖的去打掃了

命令模式的類別圖

1

命令不只有一個

現實的情況是,正常命令不會只有一個
通常媽媽請你打掃不會只負責一個區域會者永遠掃地就好

可以把Invoker裡面的Command宣告成陣列

public class MomCtrl(){
  Command[] commands;
  public MonCtrl(){
    commands = new Command[5];
    for(inti = 0; i < commands.length; i++){
      //code
    }
  }
}

命令初始化的問題

當Invoker裡面的Command如果還沒有設定,是沒有值的
如果每次都要判斷是不是null

if(command != null){
  command.execute();
}

這個不是一個聰明的方法
可以幫這一個物件設計一個沒有任何行為的物件

public class NoCommand implements Command{
  public void exccute(){}
}
//剛剛MomCtrl的程式碼就可以寫成這樣

public MonCtrl(){
    commands = new Command[5];
    Command noCommand = new Command();
    for(inti = 0; i < commands.length; i++){
      commands[i] = noCommand;
    }
  }

如此就可以避免if null的問題