鍍金池/ 教程/ HTML/ 設(shè)計模式之命令模式
代碼復(fù)用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設(shè)計模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設(shè)計模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設(shè)計模式之中介者模式
設(shè)計模式之裝飾者模式
設(shè)計模式之模板方法
設(shè)計模式之外觀模式
強大的原型和原型鏈
設(shè)計模式之構(gòu)造函數(shù)模式
揭秘命名函數(shù)表達(dá)式
深入理解J avaScript 系列(結(jié)局篇)
執(zhí)行上下文(Execution Contexts)
函數(shù)(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設(shè)計模式之適配器模式
設(shè)計模式之組合模式
設(shè)計模式之命令模式
S.O.L.I.D 五大原則之單一職責(zé) SRP
編寫高質(zhì)量 JavaScript 代碼的基本要點
求值策略
閉包(Closures)
對象創(chuàng)建模式(上篇)
This? Yes,this!
設(shè)計模式之代理模式
變量對象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向?qū)ο缶幊讨话憷碚?/span>
設(shè)計模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設(shè)計模式之迭代器模式
立即調(diào)用的函數(shù)表達(dá)式
設(shè)計模式之享元模式
設(shè)計模式之原型模式
根本沒有“JSON 對象”這回事!
JavaScript 與 DOM(下)
面向?qū)ο缶幊讨?ECMAScript 實現(xiàn)
全面解析 Module 模式
對象創(chuàng)建模式(下篇)
設(shè)計模式之職責(zé)鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設(shè)計模式之橋接模式
設(shè)計模式之策略模式
設(shè)計模式之觀察者模式
代碼復(fù)用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設(shè)計模式之工廠模式

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

介紹

命令模式(Command)的定義是:用于將一個請求封裝成一個對象,從而使你可用不同的請求對客戶進(jìn)行參數(shù)化;對請求排隊或者記錄請求日志,以及執(zhí)行可撤銷的操作。也就是說改模式旨在將函數(shù)的調(diào)用、請求和操作封裝成一個單一的對象,然后對這個對象進(jìn)行一系列的處理。此外,可以通過調(diào)用實現(xiàn)具體函數(shù)的對象來解耦命令對象與接收對象。

正文

我們來通過車輛購買程序來展示這個模式,首先定義車輛購買的具體操作類:

$(function () {
    var CarManager = {
        // 請求信息
        requestInfo: function (model, id) {
            return 'The information for ' + model +
        ' with ID ' + id + ' is foobar';
        },
        // 購買汽車
        buyVehicle: function (model, id) {
            return 'You have successfully purchased Item '
        + id + ', a ' + model;
        },
        // 組織view
        arrangeViewing: function (model, id) {
            return 'You have successfully booked a viewing of '
        + model + ' ( ' + id + ' ) ';
        }
    };
})();

來看一下上述代碼,通過調(diào)用函數(shù)來簡單執(zhí)行 manager 的命令,然而在一些情況下,我們并不想直接調(diào)用對象內(nèi)部的方法。這樣會增加對象與對象間的依賴?,F(xiàn)在我們來擴展一下這個 CarManager 使其能夠接受任何來自包括 model 和 car ID 的 CarManager 對象的處理請求。根據(jù)命令模式的定義,我們希望實現(xiàn)如下這種功能的調(diào)用:

CarManager.execute({ commandType: "buyVehicle", operand1: 'Ford Escort', operand2: '453543' });

根據(jù)這樣的需求,我們可以這樣啦實現(xiàn) CarManager.execute 方法:

CarManager.execute = function (command) {
    return CarManager[command.request](command.model, command.carID);
};

改造以后,調(diào)用就簡單多了,如下調(diào)用都可以實現(xiàn)(當(dāng)然有些異常細(xì)節(jié)還是需要再完善一下的):

CarManager.execute({ request: "arrangeViewing", model: 'Ferrari', carID: '145523' });
CarManager.execute({ request: "requestInfo", model: 'Ford Mondeo', carID: '543434' });
CarManager.execute({ request: "requestInfo", model: 'Ford Escort', carID: '543434' });
CarManager.execute({ request: "buyVehicle", model: 'Ford Escort', carID: '543434' });

總結(jié)

命令模式比較容易設(shè)計一個命令隊列,在需求的情況下比較容易將命令計入日志,并且允許接受請求的一方?jīng)Q定是否需要調(diào)用,而且可以實現(xiàn)對請求的撤銷和重設(shè),而且由于新增的具體類不影響其他的類,所以很容易實現(xiàn)。

但敏捷開發(fā)原則告訴我們,不要為代碼添加基于猜測的、實際不需要的功能,如果不清楚一個系統(tǒng)是否需要命令模式,一般就不要著急去實現(xiàn)它,事實上,在需求的時通過重構(gòu)實現(xiàn)這個模式并不困難,只有在真正需求如撤銷、恢復(fù)操作等功能時,把原來的代碼重構(gòu)為命令模式才有意義。