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

作者 | 湯姆大叔
介紹
正文
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();},// helperhasErrors: 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ī)則,就可以考慮是要策略模式來處理各種變化。
本文完?
推薦閱讀
JavaScript設(shè)計模式之構(gòu)造函數(shù)模式
學(xué)習(xí)更多技能
請點擊下方web前端開發(fā)
![]()

評論
圖片
表情
