在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 設(shè)計模式之策略模式
代碼復(fù)用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設(shè)計模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設(shè)計模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設(shè)計模式之中介者模式
設(shè)計模式之裝飾者模式
設(shè)計模式之模板方法
設(shè)計模式之外觀模式
強(qiáng)大的原型和原型鏈
設(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è)計模式之策略模式

介紹

策略模式定義了算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化不會影響到使用算法的客戶。

正文

在理解策略模式之前,我們先來一個例子,一般情況下,如果我們要做數(shù)據(jù)合法性驗證,很多時候都是按照 swith 語句來判斷,但是這就帶來幾個問題,首先如果增加需求的話,我們還要再次修改這段代碼以增加邏輯,而且在進(jìn)行單元測試的時候也會越來越復(fù)雜,代碼如下:

        validator = {
            validate: function (value, type) {
                switch (type) {
                    case 'isNonEmpty ':
                        {
                            return true; // NonEmpty 驗證結(jié)果
                        }
                    case 'isNumber ':
                        {
                            return true; // Number 驗證結(jié)果
                            break;
                        }
                    case 'isAlphaNum ':
                        {
                            return true; // AlphaNum 驗證結(jié)果
                        }
                    default:
                        {
                            return true;
                        }
                }
            }
        };
        //  測試
        alert(validator.validate("123", "isNonEmpty"));

那如何來避免上述代碼中的問題呢,根據(jù)策略模式,我們可以將相同的工作代碼單獨封裝成不同的類,然后通過統(tǒng)一的策略處理類來處理,OK,我們先來定義策略處理類,代碼如下:

var validator = {
    // 所有可以的驗證規(guī)則處理類存放的地方,后面會單獨定義
    types: {},
    // 驗證類型所對應(yīng)的錯誤消息
    messages: [],
    // 當(dāng)然需要使用的驗證類型
    config: {},
    // 暴露的公開驗證方法
    // 傳入的參數(shù)是 key => value對
    validate: function (data) {
        var i, msg, type, checker, result_ok;
        // 清空所有的錯誤信息
        this.messages = [];
        for (i in data) {
            if (data.hasOwnProperty(i)) {
                type = this.config[i];  // 根據(jù)key查詢是否有存在的驗證規(guī)則
                checker = this.types[type]; // 獲取驗證規(guī)則的驗證類
                if (!type) {
                    continue; // 如果驗證規(guī)則不存在,則不處理
                }
                if (!checker) { // 如果驗證規(guī)則類不存在,拋出異常
                    throw {
                        name: "ValidationError",
                        message: "No handler to validate type " + type
                    };
                }
                result_ok = checker.validate(data[i]); // 使用查到到的單個驗證類進(jìn)行驗證
                if (!result_ok) {
                    msg = "Invalid value for *" + i + "*, " + checker.instructions;
                    this.messages.push(msg);
                }
            }
        }
        return this.hasErrors();
    },
    // helper
    hasErrors: function () {
        return this.messages.length !== 0;
    }
};

然后剩下的工作,就是定義 types 里存放的各種驗證類了,我們這里只舉幾個例子:

// 驗證給定的值是否不為空
validator.types.isNonEmpty = {
    validate: function (value) {
        return value !== "";
    },
    instructions: "傳入的值不能為空"
};
// 驗證給定的值是否是數(shù)字
validator.types.isNumber = {
    validate: function (value) {
        return !isNaN(value);
    },
    instructions: "傳入的值只能是合法的數(shù)字,例如:1, 3.14 or 2010"
};
// 驗證給定的值是否只是字母或數(shù)字
validator.types.isAlphaNum = {
    validate: function (value) {
        return !/[^a-z0-9]/i.test(value);
    },
    instructions: "傳入的值只能保護(hù)字母和數(shù)字,不能包含特殊字符"
};

使用的時候,我們首先要定義需要驗證的數(shù)據(jù)集合,然后還需要定義每種數(shù)據(jù)需要驗證的規(guī)則類型,代碼如下:

var data = {
    first_name: "Tom",
    last_name: "Xu",
    age: "unknown",
    username: "TomXu"
};
validator.config = {
    first_name: 'isNonEmpty',
    age: 'isNumber',
    username: 'isAlphaNum'
};

最后,獲取驗證結(jié)果的代碼就簡單了:

validator.validate(data);
if (validator.hasErrors()) {
    console.log(validator.messages.join("\n"));
}

總結(jié)

策略模式定義了一系列算法,從概念上來說,所有的這些算法都是做相同的事情,只是實現(xiàn)不同,他可以以相同的方式調(diào)用所有的方法,減少了各種算法類與使用算法類之間的耦合。

從另外一個層面上來說,單獨定義算法類,也方便了單元測試,因為可以通過自己的算法進(jìn)行單獨測試。

實踐中,不僅可以封裝算法,也可以用來封裝幾乎任何類型的規(guī)則,是要在分析過程中需要在不同時間應(yīng)用不同的業(yè)務(wù)規(guī)則,就可以考慮是要策略模式來處理各種變化。