策略模式定義了算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化不會影響到使用算法的客戶。算法
在理解策略模式以前。咱們先來一個樣例,普通狀況下,假設咱們要作數據合法性驗證,很是多時候都是依照swith語句來推斷,但是這就帶來幾個問題,首先假設添加需求的話,咱們還要再次改動這段代碼以添加邏輯,而且在進行單元測試的時候也會愈來愈複雜。代碼例如如下:this
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,咱們先來定義策略處理類,代碼例如如下:spa
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裏存放的各類驗證類了,咱們這裏僅僅舉幾個樣例:code
// 驗證給定的值是否不爲空 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: "傳入的值僅僅能保護字母和數字,不能包括特殊字符" };
使用的時候。咱們首先要定義需要驗證的數據集合,而後還需要定義每種數據需要驗證的規則類型,代碼例如如下:blog
var data = {
first_name: "Tom",
last_name: "Xu",
age: "unknown",
username: "TomXu"
};
validator.config = {
first_name: 'isNonEmpty',
age: 'isNumber',
username: 'isAlphaNum'
};
最後,獲取驗證結果的代碼就簡單了:it
validator.validate(data);
if (validator.hasErrors()) {
console.log(validator.messages.join("\n"));
}
策略模式定義了一系列算法,從概念上來講,所有的這些算法都是作一樣的事情。僅僅是實現不一樣,他可以以一樣的方式調用所有的方法,下降了各類算法類與使用算法類之間的耦合。io
從另一個層面上來講,單獨定義算法類,也方便了單元測試。因爲可以經過本身的算法進行單獨測試。console
實踐中。不只可以封裝算法,也可以用來封裝差點兒不論什麼類型的規則,是要在分析過程當中需要在不一樣一時候間應用不一樣的業務規則,就可以考慮是要策略模式來處理各類變化。ast