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

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

設(shè)計(jì)模式之策略模式

介紹

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

正文

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

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

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

var validator = {
    // 所有可以的驗(yàn)證規(guī)則處理類存放的地方,后面會(huì)單獨(dú)定義
    types: {},
    // 驗(yàn)證類型所對(duì)應(yīng)的錯(cuò)誤消息
    messages: [],
    // 當(dāng)然需要使用的驗(yàn)證類型
    config: {},
    // 暴露的公開驗(yàn)證方法
    // 傳入的參數(shù)是 key => value對(duì)
    validate: function (data) {
        var i, msg, type, checker, result_ok;
        // 清空所有的錯(cuò)誤信息
        this.messages = [];
        for (i in data) {
            if (data.hasOwnProperty(i)) {
                type = this.config[i];  // 根據(jù)key查詢是否有存在的驗(yàn)證規(guī)則
                checker = this.types[type]; // 獲取驗(yàn)證規(guī)則的驗(yàn)證類
                if (!type) {
                    continue; // 如果驗(yàn)證規(guī)則不存在,則不處理
                }
                if (!checker) { // 如果驗(yàn)證規(guī)則類不存在,拋出異常
                    throw {
                        name: "ValidationError",
                        message: "No handler to validate type " + type
                    };
                }
                result_ok = checker.validate(data[i]); // 使用查到到的單個(gè)驗(yàn)證類進(jìn)行驗(yà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 里存放的各種驗(yàn)證類了,我們這里只舉幾個(gè)例子:

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

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

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

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

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

總結(jié)

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

從另外一個(gè)層面上來說,單獨(dú)定義算法類,也方便了單元測(cè)試,因?yàn)榭梢酝ㄟ^自己的算法進(jìn)行單獨(dú)測(cè)試。

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