簡易理解設(shè)計(jì)模式之:命令模式——實(shí)現(xiàn)命令的參數(shù)化配置

介紹:

命令模式是一種行為型模式。將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓用戶使用不同的請(qǐng)求把客戶端參數(shù)化;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷的操作。

備注:所謂的參數(shù)化,使用端使用執(zhí)行同一個(gè)請(qǐng)求,但是為請(qǐng)求配置不同的命令對(duì)象,那就會(huì)執(zhí)行不同的功能。例如:使用者按下一個(gè)按鈕,到底是開機(jī)還是重啟,那要看參數(shù)化配置的是哪一個(gè)具體的按鈕對(duì)象。

類圖:

命令模式UML類圖.png

Receiver(接受者角色):負(fù)責(zé)具體實(shí)施一個(gè)請(qǐng)求,執(zhí)行具體邏輯的角色。
Command(命令角色):定義好命令的接口,用來約束所有的命令對(duì)象。
ConcreteCommand(具體命令角色):實(shí)現(xiàn)Command接口,在execute方法中調(diào)用接受者角色的相關(guān)方法。
Invoker(請(qǐng)求者角色):調(diào)用命令對(duì)象執(zhí)行具體請(qǐng)求。

用法:

? 需要對(duì)行為進(jìn)行記錄、撤銷或重做、事務(wù)等處理時(shí)
? 抽象出待執(zhí)行的動(dòng)作以參數(shù)化某對(duì)象。類似過程設(shè)計(jì)中的回調(diào)機(jī)制,而命令模式是回調(diào)機(jī)制的一個(gè)面向?qū)ο蟮奶娲?/p>

個(gè)人理解:
? 命令模式核心就是將各種請(qǐng)求封裝成一個(gè)命令對(duì)象。命令對(duì)象作為一個(gè)“中間人”解耦行為請(qǐng)求者與行為執(zhí)行者。

? 用法中提到的進(jìn)行記錄、撤銷或重做、事務(wù)等處理,描述的是一些稍微復(fù)雜點(diǎn)的業(yè)務(wù),行為請(qǐng)求者實(shí)現(xiàn)一個(gè)功能時(shí)可能并不是立即執(zhí)行,甚至還需要做一些邏輯管理,這時(shí)候就需要考慮使用命令模式了。

例子:

例子1 我們使用電腦的時(shí)候,開機(jī)、關(guān)機(jī)、重啟都是作為系統(tǒng)的一條命令,用這個(gè)例子簡單介紹命令模式的結(jié)構(gòu)。

例子2 命令模式的用法中提到是回調(diào)機(jī)制的一個(gè)替代品,

1、簡單使用命令模式

1.1、定義命令接口Command接口

public interface Command {
    void execute(); //執(zhí)行命令
}

約束好所有命令子類,必須實(shí)現(xiàn)execute()方法。

1.2、實(shí)現(xiàn)接受者角色Receiver,負(fù)責(zé)具體邏輯的實(shí)現(xiàn)

分別是關(guān)機(jī)、重啟、取消三個(gè)操作的具體實(shí)現(xiàn),這里我們簡單輸出一下:

public class Receiver {

    public void shutdown(){
        System.out.println("執(zhí)行關(guān)機(jī)操作");
        System.out.print("開始關(guān)機(jī)....");
    }

    public void restart(){
        System.out.println("執(zhí)行重啟操作");
        System.out.print("開始關(guān)機(jī)....");
        System.out.print("開始開機(jī)....");
    }

    public void cancel(){
        System.out.print("取消操作");
    }
   
}

1.3、實(shí)現(xiàn)命令子類ConcreteCommand

命令子類作為“中間人”,負(fù)責(zé)執(zhí)行Recevier相關(guān)方法。

public class RestartCommand implements Command {

    private Receiver receiver;

    public RestartCommand(Receiver receiver){
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        System.out.println("命令角色執(zhí)行重啟命令");
        receiver.restart();
    }
}

省略ShutdownCommand類與CancelCommand類,結(jié)構(gòu)雷同。

1.4、創(chuàng)建Invoker,負(fù)責(zé)調(diào)用命令對(duì)象執(zhí)行請(qǐng)求

public class Invoker {
    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    public void action() {
        System.out.println("調(diào)用者執(zhí)行命令");
        command.execute();
    }
}

Invoker作為命令的調(diào)用者,讓適合的命令對(duì)象執(zhí)行命令。

1.5、測試與實(shí)現(xiàn)

public class Test {
    public static void main(String[] args) {
        //構(gòu)造一個(gè)接受者對(duì)象
        Receiver receiver = new Receiver();
        //根據(jù)接受者對(duì)象創(chuàng)建一條命令
        Command command = new RestartCommand(receiver);
        //根據(jù)具體命令對(duì)象構(gòu)造請(qǐng)求者
        Invoker invoker = new Invoker(command);
        //執(zhí)行命令
        invoker.action();
    }
}
調(diào)用者執(zhí)行命令
命令角色執(zhí)行重啟命令
執(zhí)行重啟操作
開始關(guān)機(jī)....
開始開機(jī)....

關(guān)機(jī)重啟的例子簡單實(shí)現(xiàn)就完成了。讀到這里只是能體會(huì)到這個(gè)模式能解耦和具體結(jié)構(gòu),實(shí)際開發(fā)中用處不怎么大。例如,我們關(guān)機(jī)的時(shí)候通常會(huì)遇到以下情況:某個(gè)應(yīng)用程序還卡住了,關(guān)不了機(jī),重啟不了,這種情況怎么處理呢?

1.6、改進(jìn)一下Invoker

public class Invoker {

    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    public void action(boolean process) {
        if (process){
            System.out.print("進(jìn)程還沒退出,終止命令!");
            return;
        }
        System.out.println("調(diào)用者執(zhí)行命令");
        command.execute();
    }
    
}

action()方法加多個(gè)邏輯,判斷后臺(tái)進(jìn)程是否全部退出。我們發(fā)現(xiàn),Invoker請(qǐng)求者負(fù)責(zé)接受命令對(duì)象,并作出邏輯判斷,最后調(diào)用命令對(duì)象,甚至直接理解成它是一個(gè)命令管理者CommandController。

2、代替回調(diào)機(jī)制

我另外一篇文章詳細(xì)分析過回調(diào)機(jī)制,觀察者模式——監(jiān)聽與回調(diào),大家可以去看看。

下面簡單寫一下回調(diào)機(jī)制:

2.1、回調(diào)類

public interface ICallBack {
    void callback();
}

2.2、需要執(zhí)行回調(diào)的類

public class A {
    private ICallBack callBack;

    public void setCallBack(ICallBack callBack){
        this.callBack = callBack;
    }

    public void doSomething(){
        System.out.print("do something!");
        if (callBack != null){
            callBack.callback();
        }
    }
}

2.3、實(shí)現(xiàn)

public class Client {

    public static void main(String[] args) {
        A a = new A();
        a.setCallBack(new ICallBack() {
            @Override
            public void callback() {
                System.out.print("執(zhí)行回調(diào)");
            }
        });
        a.doSomething();
    }
}

2.4、命令模式代替回調(diào)機(jī)制

public class ConcreteCommand implements ICallBack{
    @Override
    public void callback() {
        System.out.print("執(zhí)行回調(diào)");
    }
}
public class Client {

    public static void main(String[] args) {
        A a = new A();
        a.setCallBack(new ConcreteCommand());//改了這里
        a.doSomething();
    }
}

回調(diào)機(jī)制:回調(diào)(Callback)函數(shù)是指函數(shù)先在某處注冊(cè),而它將在稍后某個(gè)需要的時(shí)候被調(diào)用,它實(shí)際上是一種參數(shù)化機(jī)制。

命令模式:命令模式的設(shè)計(jì)意圖就是“將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使用戶可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化”。

看下代碼,用具體命令對(duì)象類代替了匿名類回調(diào)函數(shù),同樣都是參數(shù)化的配置機(jī)制,就稱為代替了。本質(zhì)上,以上其實(shí)是兩種回調(diào)的寫法。

總結(jié):

? 命令模式理解上比較簡單,但使用上相對(duì)來說比較繁瑣,一個(gè)簡單的調(diào)用關(guān)系被解耦成多個(gè)部分。

? 用命令模式的參數(shù)化概念再回顧一下回調(diào)

? 在備忘錄模式中同樣提到撤銷重做這個(gè)業(yè)務(wù)。如果在某個(gè)系統(tǒng)使用命令模式時(shí),需要實(shí)現(xiàn)命令的撤銷功能,那么命令模式可以使用備忘錄模式來存儲(chǔ)可撤銷操作的狀態(tài)。

感謝您的閱讀~

轉(zhuǎn)載請(qǐng)注明出處喔:http://m.itdecent.cn/p/1a6767821e9d

推薦閱讀

基礎(chǔ)篇:
設(shè)計(jì)模式前篇之——UML類圖必會(huì)知識(shí)點(diǎn)
設(shè)計(jì)模式前篇之——一起過一下面向?qū)ο蟮母拍?/a>
創(chuàng)建型模式:
簡易理解設(shè)計(jì)模式之:簡單工廠模式——來試試接入支付功能
簡易理解設(shè)計(jì)模式之:工廠方法模式——數(shù)據(jù)存儲(chǔ)例子
簡易理解設(shè)計(jì)模式之:抽象工廠模式——更換數(shù)據(jù)庫例子
簡易理解設(shè)計(jì)模式之:建造者模式——學(xué)習(xí)使用“鏈?zhǔn)秸{(diào)用”
簡易理解設(shè)計(jì)模式之:原型模式——深、淺拷貝的概念
簡易理解設(shè)計(jì)模式之:單例模式——單例模式的幾種常用寫法
結(jié)構(gòu)型模式:
簡易理解設(shè)計(jì)模式之:適配器模式——Android列表視圖控件設(shè)計(jì)方式
簡易理解設(shè)計(jì)模式之:橋接模式——穿衣服經(jīng)典案例2
簡易理解設(shè)計(jì)模式之:組合模式——實(shí)現(xiàn)View中的樹狀結(jié)構(gòu)
簡易理解設(shè)計(jì)模式之:裝飾模式——穿衣服經(jīng)典案例
簡易理解設(shè)計(jì)模式之:外觀模式——第三方SDK的幫助類
簡易理解設(shè)計(jì)模式之:享元模式——五子棋游戲例子
簡易理解設(shè)計(jì)模式之:代理模式——iOS視圖控件設(shè)計(jì)方式
行為型模式:
簡易理解設(shè)計(jì)模式之:策略模式——優(yōu)化一下支付功能
簡易理解設(shè)計(jì)模式之:模板方法模式——Android中的BaseActivity基類
簡易理解設(shè)計(jì)模式之:觀察者模式——監(jiān)聽與回調(diào)
簡易理解設(shè)計(jì)模式之:狀態(tài)模式——優(yōu)化登錄操作
簡易理解設(shè)計(jì)模式之:備忘錄模式——Word文檔的工作原理
簡易理解設(shè)計(jì)模式之:迭代器模式——遍歷對(duì)象的好幫手
簡易理解設(shè)計(jì)模式之:命令模式——實(shí)現(xiàn)命令的參數(shù)化配置
簡易理解設(shè)計(jì)模式之:責(zé)任鏈模式——OA中請(qǐng)假流程示例
簡易理解設(shè)計(jì)模式之:中介者模式——多人聊天室例子
簡易理解設(shè)計(jì)模式之:解釋器模式——語言和文法
簡易理解設(shè)計(jì)模式之:訪問者模式——員工考核例子

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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