深入理解JavaScript系列(33):設計模式之策略模式

來源:互聯網
上載者:User

標籤:javascript

介紹

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

本文

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

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

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

var validator = {    // 所有可以的驗證規則處理類存放的地方,後面會單獨定義    types: {},    // 驗證類型所對應的錯誤訊息    messages: [],    // 當然需要使用的驗證類型    config: {},    // 暴露的公開驗證方法    // 傳入的參數是 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];  // 根據key查詢是否有存在的驗證規則                checker = this.types[type]; // 擷取驗證規則的驗證類                if (!type) {                    continue; // 如果驗證規則不存在,則不處理                }                if (!checker) { // 如果驗證規則類不存在,拋出異常                    throw {                        name: "ValidationError",                        message: "No handler to validate type " + type                    };                }                result_ok = checker.validate(data[i]); // 使用查到到的單個驗證類進行驗證                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: "傳入的值不可為空"};// 驗證給定的值是否是數字validator.types.isNumber = {    validate: function (value) {        return !isNaN(value);    },    instructions: "傳入的值只能是合法的數字,例如:1, 3.14 or 2010"};// 驗證給定的值是否只是字母或數字validator.types.isAlphaNum = {    validate: function (value) {        return !/[^a-z0-9]/i.test(value);    },    instructions: "傳入的值只能保護字母和數字,不能包含特殊字元"};

使用的時候,我們首先要定義需要驗證的資料集合,然後還需要定義每種資料需要驗證的規則類型,代碼如下:

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

最後,擷取驗證結果的代碼就簡單了:

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

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

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

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

著作權聲明:本文為博主http://www.zuiniusn.com原創文章,未經博主允許不得轉載。

深入理解JavaScript系列(33):設計模式之策略模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.