設(shè)計(jì)模式之命令模式

模擬需求

現(xiàn)在需要設(shè)計(jì)一個(gè)遙控器。
廠商的類可能是這樣的:

圖片.png

這些類看起來不少,而且接口各有差異,而且這些類以后還會(huì)越來越多。所以設(shè)計(jì)一個(gè)遙控器API很有挑戰(zhàn)性。
使用命令模式可以將“動(dòng)作的請(qǐng)求者” 從“動(dòng)作的執(zhí)行者”對(duì)象中解耦。請(qǐng)求者可以是遙控器,而執(zhí)行者對(duì)象就是廠商類其中之一的實(shí)例。

// 實(shí)現(xiàn)命令的接口
//首先讓所有的命令對(duì)象實(shí)現(xiàn)相同的包含一個(gè)方法的接口
public interface Command(){
    public void execute();
}
//實(shí)現(xiàn)一個(gè)打開電燈的命令
public class LightOnCommand implements Command{
   Light light;
   //構(gòu)造器傳入電燈,以便讓這個(gè)命令控制
   public LightOnCommand(Light light){
     this.light  = light;
   }
  //這個(gè)方法調(diào)用接收對(duì)象(我們正在使用的電燈)的on()方法
   public void execute(){
     light.on()
  }
}
//使用命令對(duì)象
public class SimpleRemoteControl{
  //有一個(gè)插槽持有命令,而這個(gè)命令控制著一個(gè)裝置
  Command slot;
  //用來設(shè)置插槽控制的命令
  public SimpleRemoteControl(){}
  public void setCommand(Command command){
    slot = command;
  }
  //當(dāng)按下按鈕時(shí),這個(gè)方法就會(huì)被調(diào)用
  publlic void buttonWasPressed(){
    slot.execute();
  }
}
//客戶端控制代碼
public class RemoteControlTest{
  public static void main(String[] args){
     // 調(diào)用者
    SimpleRemoteControl remote = new SimpleRemoteControl;
    //接收者
    Light light = new Light();
    //命令
    LightOnCommand lightOn = new LightOnCommand(light);
    //把命令傳給調(diào)用者
    remote.setCommand(lightOn);
    remote.buttonWasPressed();
  }
}

將請(qǐng)求封裝成對(duì)象,以便使用不同的請(qǐng)求、隊(duì)列或者日志來參數(shù)化其他對(duì)象,命令模式也可以支持撤銷的操作。
一個(gè)命令對(duì)象通過在特定接收者上綁定一組動(dòng)作來封裝一個(gè)請(qǐng)求,要達(dá)到這一點(diǎn),命令對(duì)象將動(dòng)作和接收者包進(jìn)對(duì)象,這個(gè)對(duì)象只暴露出一個(gè)execute()方法,當(dāng)此方法被調(diào)用時(shí),接收者就會(huì)進(jìn)行這些動(dòng)作。從外表上看來,其他對(duì)象不知道究竟哪個(gè)接收者進(jìn)行了哪些動(dòng)作,只知道調(diào)用execute()方法,請(qǐng)求的目的就能達(dá)到。

定義命令模式類圖

圖片.png

命令模式的更多用途 :隊(duì)列請(qǐng)求

命令可以將運(yùn)算塊打包(一個(gè)接收者和一組動(dòng)作),然后將它 傳來傳去,就像是一般的對(duì)象一樣。閑著,即使在命令對(duì)象被創(chuàng)建許久之后,運(yùn)算依然可以被調(diào)用。事實(shí)上,它甚至可以在不同的線程中被調(diào)用。我們可以利用這一特性衍生一些應(yīng)用。例如:日志安排(Scheduler)、線程池、工作隊(duì)列等。
想象一個(gè)工作隊(duì)列:在某一端添加命令,然后另一端另一端則是線程。線程進(jìn)行下面的動(dòng)作:從隊(duì)列中取出一個(gè)命令,調(diào)用它的execute()方法,等待這個(gè)調(diào)用完成,然后將此命令對(duì)象丟棄,再取出下一個(gè)命令····
工作隊(duì)列類和計(jì)算的對(duì)象之間完全是解耦的。此刻線程可能在進(jìn)行財(cái)務(wù)運(yùn)算,下一刻卻在讀取網(wǎng)絡(luò)數(shù)據(jù)。它們只知道取出命令對(duì)象,然后調(diào)用execute()方法。

  • 命令對(duì)象將發(fā)出請(qǐng)求 的對(duì)象和執(zhí)行請(qǐng)求的對(duì)象解耦
  • 在被解耦的兩者之間是通過命令對(duì)象進(jìn)行溝通的。命令對(duì)象封裝了接收者和一個(gè)或一組動(dòng)作。
  • 調(diào)用者可以接受命令當(dāng)作參數(shù),甚至在運(yùn)行時(shí)動(dòng)態(tài)的進(jìn)行。
  • 命名可以支持撤銷,做法是實(shí)現(xiàn)一個(gè)undo()方法來回到execute()被執(zhí)行前的狀態(tài)。
  • 宏命令是命令的一種簡(jiǎn)單的延伸,允許調(diào)用多個(gè)命令。宏方法也可以支持撤銷
  • 命令也可以用來實(shí)現(xiàn)日志和事務(wù)系統(tǒng)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容