19避除、命令模式(Command Pattern)

1. 命令模式

1.1 簡(jiǎn)介

??命令模式(Command Pattern)是一種數(shù)據(jù)驅(qū)動(dòng)的設(shè)計(jì)模式,它屬于行為型模式究履。請(qǐng)求以命令的形式包裹在對(duì)象中滤否,并傳給調(diào)用對(duì)象。調(diào)用對(duì)象尋找可以處理該命令的合適的對(duì)象最仑,并把該命令傳給相應(yīng)的對(duì)象藐俺,該對(duì)象執(zhí)行命令炊甲。

??將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓你使用不同的請(qǐng)求把客戶端參數(shù)化欲芹,對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志卿啡,可以提供命令的撤銷(xiāo)和恢復(fù)功能。 (來(lái)自《設(shè)計(jì)模式之禪》)

1.2 結(jié)構(gòu)

Command模式uml:

Command模式uml.jpg

Command模式角色:

  • Command:定義命令的接口菱父,聲明執(zhí)行的方法颈娜。
  • ConcreteCommand: 具體的命令, 實(shí)現(xiàn)命令接口浙宜;通常會(huì)持有接收者官辽,并調(diào)用接收者的功能來(lái)完成命令要執(zhí)行的操作。
  • Receiver:接收者粟瞬,真正執(zhí)行命令的對(duì)象同仆。任何類(lèi)都可能成為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能裙品。
  • Invoker:要求命令對(duì)象執(zhí)行請(qǐng)求俗批,通常會(huì)持有命令對(duì)象,可以持有很多的命令對(duì)象市怎。這個(gè)是客戶端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方岁忘,也就是說(shuō)相當(dāng)于使用命令對(duì)象的入口。
  • Client: 創(chuàng)建具體的命令對(duì)象区匠,并且設(shè)置命令對(duì)象的接收者干像。注意這個(gè)不是我們常規(guī)意義上的客戶端,而是在組裝命令對(duì)象和接收者辱志,或許蝠筑,把這個(gè)Client稱(chēng)為裝配者會(huì)更好理解,因?yàn)檎嬲褂妹畹目蛻舳耸菑腎nvoker來(lái)觸發(fā)執(zhí)行揩懒。

2. 示例

??司令員下令讓士兵去干件事情什乙,從整個(gè)事情的角度來(lái)考慮,司令員的作用是已球,發(fā)出口令臣镣,口令經(jīng)過(guò)傳遞,傳到了士兵耳朵里智亮,士兵去執(zhí)行忆某。這個(gè)過(guò)程好在,三者相互解耦阔蛉,任何一方都不用去依賴(lài)其他人弃舒,只需要做好自己的事兒就行,司令員要的是結(jié)果,不會(huì)去關(guān)注到底士兵是怎么實(shí)現(xiàn)的聋呢。

??Invoker是調(diào)用者(司令員)苗踪,Receiver是被調(diào)用者(士兵),MyCommand是命令削锰,實(shí)現(xiàn)了Command接口通铲,持有接收對(duì)象。

** Command:**

public interface Command {  
   public void exe();  
}

** MyCommand:**

public class MyCommand implements Command {  
 
   private Receiver receiver;  
     
   public MyCommand(Receiver receiver) {  
       this.receiver = receiver;  
   }  
 
   @Override  
   public void exe() {  
       receiver.action();  
   }  
}  

** Receiver:**

public class Receiver {  
   public void action(){  
       System.out.println("command received!");  
   }  
} 

** Invoker:**

public class Invoker {  
     
   private Command command;  
     
   public Invoker(Command command) {  
       this.command = command;  
   }  
 
   public void action(){  
       command.exe();  
   }  
}  

** 調(diào)用示例:**

   public static void main(String[] args) {  
       Receiver receiver = new Receiver();  
       Command cmd = new MyCommand(receiver);  
       Invoker invoker = new Invoker(cmd);  
       invoker.action();  
   } 

3. 總結(jié)

??命令模式的目的就是達(dá)到命令的發(fā)出者和執(zhí)行者之間解耦器贩,實(shí)現(xiàn)請(qǐng)求和執(zhí)行分開(kāi)颅夺,熟悉Struts的同學(xué)應(yīng)該知道,Struts其實(shí)就是一種將請(qǐng)求和呈現(xiàn)分離的技術(shù)蛹稍,其中必然涉及命令模式的思想吧黄!

命令模式優(yōu)點(diǎn):

  • 降低了系統(tǒng)耦合度。
  • 命令模式的封裝性很好:每個(gè)命令都被封裝起來(lái)唆姐,對(duì)于客戶端來(lái)說(shuō)稚字,需要什么功能就去調(diào)用相應(yīng)的命令,而無(wú)需知道命令具體是怎么執(zhí)行的厦酬。比如有一組文件操作的命令:新建文件、復(fù)制文件瘫想、刪除文件仗阅。如果把這三個(gè)操作都封裝成一個(gè)命令類(lèi),客戶端只需要知道有這三個(gè)命令類(lèi)即可国夜,至于命令類(lèi)中封裝好的邏輯减噪,客戶端則無(wú)需知道。
  • 命令模式的擴(kuò)展性很好车吹,在命令模式中筹裕,在接收者類(lèi)中一般會(huì)對(duì)操作進(jìn)行最基本的封裝,命令類(lèi)則通過(guò)對(duì)這些基本的操作進(jìn)行二次封裝窄驹,當(dāng)增加新命令的時(shí)候朝卒,對(duì)命令類(lèi)的編寫(xiě)一般不是從零開(kāi)始的,有大量的接收者類(lèi)可供調(diào)用乐埠,也有大量的命令類(lèi)可供調(diào)用抗斤,代碼的復(fù)用性很好。比如丈咐,文件的操作中瑞眼,我們需要增加一個(gè)剪切文件的命令,則只需要把復(fù)制文件和刪除文件這兩個(gè)命令組合一下就行了棵逊,非常方便伤疙。
  • 可以實(shí)現(xiàn)宏命令。命令模式可以與組合模式結(jié)合辆影,將多個(gè)命令裝配成一個(gè)組合命令徒像,即宏命令黍特。
  • 方便實(shí)現(xiàn) Undo 和 Redo 操作。命令模式可以與后面介紹的備忘錄模式結(jié)合厨姚,實(shí)現(xiàn)命令的撤銷(xiāo)與恢復(fù)衅澈。
  • 增加或刪除命令非常方便。采用命令模式增加與刪除命令不會(huì)影響其他類(lèi)谬墙,它滿足“開(kāi)閉原則”今布,對(duì)擴(kuò)展比較靈活。

命令模式缺點(diǎn):

  • 使用命令模式可能會(huì)導(dǎo)致某些系統(tǒng)有過(guò)多的具體命令類(lèi)拭抬。因?yàn)獒槍?duì)每一個(gè)命令都需要設(shè)計(jì)一個(gè)具體命令類(lèi)部默,因此某些系統(tǒng)可能需要大量具體命令類(lèi),這將影響命令模式的使用造虎。

命令模式適用場(chǎng)景:

  • struts 1 中的 action 核心控制器 ActionServlet 只有一個(gè)傅蹂,相當(dāng)于 Invoker,而模型層的類(lèi)會(huì)隨著不同的應(yīng)用有不同的模型類(lèi)算凿,相當(dāng)于具體的 Command份蝴。
  • 系統(tǒng)需要將請(qǐng)求調(diào)用者和請(qǐng)求接收者解耦,使得調(diào)用者和接收者不直接交互氓轰。
  • 系統(tǒng)需要在不同的時(shí)間指定請(qǐng)求婚夫、將請(qǐng)求排隊(duì)和執(zhí)行請(qǐng)求。
  • 系統(tǒng)需要支持命令的撤銷(xiāo)(Undo)操作和恢復(fù)(Redo)操作署鸡。
  • 系統(tǒng)需要將一組操作組合在一起案糙,即支持宏命令。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末靴庆,一起剝皮案震驚了整個(gè)濱河市时捌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炉抒,老刑警劉巖奢讨,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異焰薄,居然都是意外死亡禽笑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)蛤奥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)佳镜,“玉大人,你說(shuō)我怎么就攤上這事凡桥◇吧欤” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)啊掏。 經(jīng)常有香客問(wèn)我蠢络,道長(zhǎng),這世上最難降的妖魔是什么迟蜜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任刹孔,我火速辦了婚禮,結(jié)果婚禮上娜睛,老公的妹妹穿的比我還像新娘髓霞。我一直安慰自己,他們只是感情好畦戒,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布方库。 她就那樣靜靜地躺著,像睡著了一般障斋。 火紅的嫁衣襯著肌膚如雪纵潦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天垃环,我揣著相機(jī)與錄音邀层,去河邊找鬼。 笑死遂庄,一個(gè)胖子當(dāng)著我的面吹牛被济,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涧团,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼经磅!你這毒婦竟也來(lái)了泌绣?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤预厌,失蹤者是張志新(化名)和其女友劉穎阿迈,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體轧叽,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苗沧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炭晒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片待逞。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖网严,靈堂內(nèi)的尸體忽然破棺而出识樱,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布怜庸,位于F島的核電站当犯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏割疾。R本人自食惡果不足惜嚎卫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宏榕。 院中可真熱鬧拓诸,春花似錦、人聲如沸担扑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)涌献。三九已至胚宦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燕垃,已是汗流浹背枢劝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卜壕,地道東北人您旁。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像轴捎,于是被迫代替她去往敵國(guó)和親鹤盒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360