<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

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

    共 3392字,需瀏覽 7分鐘

     ·

    2021-03-29 10:34

    作者 | 湯姆大叔


    介紹

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

    正文

    在理解策略模式之前,我們先來一個(gè)例子,一般情況下,如果我們要做數(shù)據(jù)合法性驗(yàn)證,很多時(shí)候都是按照swith語句來判斷,但是這就帶來幾個(gè)問題,首先如果增加需求的話,我們還要再次修改這段代碼以增加邏輯,而且在進(jìn)行單元測試的時(shí)候也會越來越復(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;                }        }    }};// 測試alert(validator.validate("123", "isNonEmpty"));

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

    var validator = {
    // 所有可以的驗(yàn)證規(guī)則處理類存放的地方,后面會單獨(dú)定義 types: {},
    // 驗(yàn)證類型所對應(yīng)的錯(cuò)誤消息 messages: [],
    // 當(dāng)然需要使用的驗(yàn)證類型 config: {},
    // 暴露的公開驗(yàn)證方法 // 傳入的參數(shù)是 key => value對 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é)果的代碼就簡單了:

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

    總結(jié)

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

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

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

    本文完?


    推薦閱讀

    JavaScript設(shè)計(jì)模式之單例模式

    JavaScript設(shè)計(jì)模式之構(gòu)造函數(shù)模式

    設(shè)計(jì)模式之建造者模式

    設(shè)計(jì)模式之工廠模式

    設(shè)計(jì)模式之裝飾者模式

    設(shè)計(jì)模式之外觀模式

    設(shè)計(jì)模式之代理模式

    設(shè)計(jì)模式之觀察者模式


    學(xué)習(xí)更多技能

    請點(diǎn)擊下方web前端開發(fā)


    瀏覽 22
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評論
    圖片
    表情
    推薦
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    亚洲经典视频 | 懂色av懂色av粉嫩av | 日韩黄色视频免费看 | 久久夜色精品国产亚洲AV | 俺去了久久 |