行為型模式(五):命令模式

命令模式屬于23種設計模式中行為模式中的一個,它也是一種簡單實用非常普遍的設計模式。
首先看下GOF對命令模式的定義:將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。
命令模式主要應用于將行為調用者與實現者解耦。比如我們以前慣用的寫代碼的方式是LogicProcess logic = new LogicProcess(); 然后緊接著調用實現方法logic.process(),這種寫法其實非常普遍,但這種寫法把行為調用者和行為實現者耦合在了一起,一般情況下并沒有什么問題的,但當調用邏輯比較復雜或則調用行為有多種實現時就非常不利于程序的擴展。
命令模式的適用場景描述:
(1)整個調用過程比較繁雜,或者存在多處這種調用。使用Command類對該調用加以封裝,便于功能的再利用。
(2)調用前后需要對調用參數進行某些處理。
(3)調用前后需要進行某些額外處理,比如日志,緩存,記錄歷史操作等。
命令模式結構圖如下:

img

wKioL1MXQNnzDmOuAAE_6jCA_qk028.jpg

命令模式的參與角色:
(1)抽象命令角色(Command):抽象命令,包含命令執行的抽象方法
(2)命令接收者(Receiver):命令接收者角色,它包含所有命令的具體行為實現方法。
(3)具體命令角色(ConcreteCommand):它包含一個命令接收者對象,并調用接收者的對象相應實現方法。
(4)命令調用者角色(Invoker):提供給客戶端調用,接收客戶端所傳遞的具體命令對象。
下面看具體代碼實現:
1、第一個文件抽象命令角色:Command.java

/**
* 抽象命令接口
*/
public interface Command {
/**
* 命令執行方法
*/
public void execute();
}

2、第二個文件命令接收者角色:Document.java

/**
* 命令接收者 Receiver
*/
public class Document {
/**
* 操作實體對象
*/
public static StringBuffer sbr = new StringBuffer();
/**
* 計數器
*/
public static int count = 0;
/**
* 撤銷實現方法
*/
public void undo(){
System.out.println("調用撤銷實現方法,字符串遞減");
sbr.deleteCharAt(sbr.length()-1);
count --;
System.out.println("當前文本為:" + sbr.toString());
}
/**
* 恢復實現方法
*/
public void redo(){
System.out.println("調用恢復實現方法,字符串遞加");
this.sbr.append(count);
count ++;
System.out.println("當前文本為:" + sbr.toString());
}
/**
* 執行實現方法
*/
public void add(){
System.out.println("調用執行實現方法,字符串遞加");
this.sbr.append(count);
count ++;
System.out.println("當前文本為:" + sbr.toString());
}
}

3、第三個文件具體命令角色:AddCommand.java

/**
* 執行命令實現類
*/
public class AddCommand implements Command {
/**
* 命令接受者對象
*/
public Document doucment;
/**
* 構造方法
* @param document
*/
public AddCommand(Document document){
this.doucment = document;
}
@Override
public void execute() {
// TODO Auto-generated method stub
this.doucment.add();
}

4、第四個文件具體命令角色:UndoCommand.java

/**
* 撤銷命令實現類
*/
public class UndoCommand implements Command {
/**
* 命令接受者對象
*/
public Document doucment;
/**
* 構造方法
* @param document
*/
public UndoCommand(Document document){
this.doucment = document;
}
@Override
public void execute() {
// TODO Auto-generated method stub
this.doucment.undo();
}
}

5、第五個文件具體命令角色:RedoCommand.java

/**
* 恢復命令實現類
*/
public class RedoCommand implements Command {
/**
* 命令接受者對象
*/
public Document doucment;
/**
* 構造方法
* @param document
*/
public RedoCommand(Document document){
this.doucment = document;
}
@Override
public void execute() {
// TODO Auto-generated method stub
this.doucment.redo();
}
}

6、第六個文件調用者角色:Invoker.java

/**
* 提供給客戶端的命令調用方法
* @author feng
*
*/
public class Invoker {
/**
* 命令對象
*/
public Command command;
/**
* 命令設置方法
* @param command
*/
public void setCommand(Command cmd){
this.command = cmd;
}
/**
* 命令執行方法
*/
public void execute(){
this.command.execute();
}
}

7、第七個文件TestMain.java

/**
* 測試Main方法
*/
public class TestMain {
public static void main(String args[]){
Document doc = new Document(); //文檔實體對象
AddCommand addCmd = new AddCommand(doc); //具體命令實體對象
UndoCommand undoCmd = new UndoCommand(doc); //具體命令實體對象
RedoCommand redoCmd = new RedoCommand(doc); //具體命令實體對象
Invoker invoker = new Invoker(); //調用者對象
invoker.setCommand(addCmd);
invoker.execute();
invoker.setCommand(addCmd);
invoker.execute();
invoker.setCommand(undoCmd);
invoker.execute();
invoker.setCommand(redoCmd);
invoker.execute();
}

雖然代碼看似挺多,但其實命令模式的結構還是比較清晰的,總的來說命令模式的使用流程就是首先創建一個抽象命令,然后創建多個具體命令實現抽象命令接口,然后創建一個命令接受者角色,它包含各種的行為的具體實現,然后再有一個命令調用者角色,提供給客戶端,用于接收客戶端的參數。
下面總結下命令模式的優點:
(1)命令模式將行為調用者和各種行為分隔開,降低程序的耦合,便于程序擴展。
(2)命令模式將行為的具體實現封裝起來,客戶端無需關心行為的具體實現。
(3)命令模式可為多種行為提供統一的調用入口,便于程序對行為的管理和控制。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容