實例場景:java
一、餐館點菜吃飯:當咱們在餐館進行點菜的時候,通常咱們會進行點菜,而後服務員下訂單,而後廚師根據訂單進行炒菜,最後擺在咱們面前的就是一盤美味佳餚了。程序員
二、領導下命令:領導要員工作事的時候,通常是把事情告訴祕書或行政人員,而後由她們把領導安排的事情下發到員工。設計模式
三、當咱們想要聽音樂,只要咱們按下播放鍵盤,相應的音樂就自動播放了。架構
以上場景中咱們都使用了一種設計模式:命令模式框架
命令模式把一個請求或者操做封裝到一個對象中。命令模式運行系統使用不一樣的請求把客戶端參數化,對請求排隊或者記錄請求日誌,能夠提供命令的撤銷和恢復功能。ide
命令模式中是把一個命令封裝爲一個對象。
測試
命令模式的角色:ui
客戶角色:建立一個具體命令對象,並肯定其接受者this
命令角色:聲明一個給全部具體命令類的抽象接口,這是一個抽象角色,一般由一個接口或抽象類實現。spa
具體命令角色:定義接收者和行爲之間的弱耦合,實現execute方法,負責調用接收者的相應操做。
請求者角色:負責調用命令對象執行請求。
接收者角色:負責具體實施和執行一個請求。
在上面的實例場景中,場景分析以下:
一、餐館點菜,咱們至關與一個客戶角色,咱們點菜就是發送命令,不一樣的人或有不一樣的命令請求,就應該把命令設計爲抽象類,用戶發出的請求就是具體的命令,服務員就是一個請求者,她把命令也就是客戶的訂單給接受者廚師,廚師只要照着菜單作菜,作好後給客戶便可,客戶不用去管菜是怎樣作出來的,只要發送一個命令,而後獲得本身的結果就能夠了。
二、領導下命令:我是老總,我只管發個命令,至於這個命令發給誰,誰執行,關我P事,我發錢請人不是爲了給本身找麻煩。你是負責事情的員工,你的天職是作好上級交給你的任務,踏踏實實,不要知道太多,不要八卦,不要問太多了。Client對象是發佈命令的。Invoker對象是傳遞命令的,就是跑腿的。Receiver是受氣包,底層最累的程序員,負責幹活吧
三、一個Mp3。你按了一個播放鍵盤,就播放了。這就能夠算是命令模式的一種。 你是Client ,按鍵是Invoker,mp3是Receiver,播放就是一個命令Command對象。
命令模式的好處:
◆很容易構造一個命令隊列
◆記錄相關的命令日誌
◆增長命令的狀態,實現命令的撤銷和重作
◆容許接受請求的一方決定是否可作
◆新的命令垂手可得能夠加入其中
缺點:可能會有過多的具體命令類存在
場景代碼實現:
package cn.com.command; //聲明一個命令角色 public interface Command { public void execute(); }
package cn.com.command; //定義一個接收者,至關與一個廚師 //負責具體實施和執行一個請求 public class Recevier { public void doAction(){ System.out.println("客戶發訂單了,我要炒菜了"); } }
package cn.com.command; //具體的命令角色,負責調用接收者相應的操做 public class ConcreteCommand implements Command{ private Recevier recevier; public ConcreteCommand(Recevier recevier){ this.recevier=recevier; } @Override public void execute() { recevier.doAction(); } }
package cn.com.command; //定義一個請求者角色, //負責調用命令對象,執行請求 public class Invoker { private Command command; public Invoker(Command command){ this.command=command; } public void doInvokerAction(){ command.execute(); } }
package cn.com.command; //建立客戶角色,客戶進行點菜 public class Client { public static void main(String[] args) { //生成一個具體的廚師角色 Recevier recevier=new Recevier(); //生成一個菜單命令對象 Command command=new ConcreteCommand(recevier); //服務員把菜單給廚師,廚師具體實施,進行炒菜 Invoker invoker=new Invoker(command); invoker.doInvokerAction(); //在整個應用場景中,其實是請求者調用具體命令對象,具體命令對象調用接收者 } }
客戶發訂單了,我要炒菜了
//在整個應用場景中,其實是請求者調用具體命令對象,具體命令對象調用接收者
在JUnit框架中,運用了咱們的命令模式:
用戶編寫測試用例TestCase,把這些測試用例組成請求(多是一個或者多個),發送到JUnit,而後由JUnit執行,最後報告詳細測試結果包括執行的時間,錯誤方法,錯誤位置等。這樣測試用例的開發人員就不須要知道請求TestCase的具體操做信息,僅把它看成一種命令來執行,而後把執行測試結果發給測試人員。這樣就使JUnit框架和TestCase的開發人員獨立開來,使得請求的一方沒必要知道接收請求一方的詳細信息,更沒必要知道是怎樣被接收,以及怎樣被執行的,實現系統的鬆藕合。
使用命令模式後給JUnit系統的架構帶來的效果:
a、將實現請求的一方(TestCase開發)和調用一方JUnit進行解耦
b、使新的TestCase很容易加入,無需改變已有的類,只需繼承TestCase類便可,這樣方便了測試人員
c、能夠將多個TestCase進行組合成一個複合命令,TestSuit就是它的複合命令,使用了組合模式
d、容易把請求的TestCase組成請求隊列,這樣使接收請求的一方JUnit框架,容易決定是否執行請求,一旦發現測試用例失敗或者錯誤能夠當即中止進行報告