Javascript Patterns--读书笔记10 (Strategy)
Strategy模式允许你在运行的时候可以选择不同的算法。你的代码可以提供一个统一的接口,但是指定的任务可以根据不同的上下文来选择不同的算不了法。
来看一个用strategy模式来解决问题的例子:表单检查。你可以创建一个validate()方法。我们用这个方法来检验表单,而不管这个表单是什么类型的表单,我们所要得到的是一个正确的数据。
而真正我们需要实现的是,根据具体的form类型,可以选择不同的类型检查器来检查。你的validator将会选取最好的策略来处理这个task,然后用最合适的算法来检查。
Data Validation Example
下面的数据,来自一个页面,我们来检查一下它们的有效性:
var data = { first_name: "Super", last_name: "Man", age: "unknown", username: "o_0" }
对validator来说,什么是最好的策略对这个具体的实例,你必须首先配置这个validator并且设置一系列的规则来决定那些是有效的。
具体来说,你在做姓名检查时,不需要last_name,可以接受任意的字符做为fist_name,但是你需要年龄是Number, username只能包含字母和数字并且不能包含特殊的符号。我们可以列出下列的configuration:
validator.config = { first_name: "isNonEmpty', age: 'isNumber', username: 'isAlphaNum' }
现在validator对象已经配置好了,可以来处理上边的数据了,我们看一下如何来调用validate()
validator.validate(data); if(validator.hasErrors()){ console.log(validator.message.join("\n"); }
得到的结果将会是
Invalid value for *age*, the value can only be a valid number, e.g.1, 3.14 or 2010
Invalid value for *username*, the value can only contain characters and numbers, no special symbols
现在让我们来看一下如何实现这个validators.
实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//check for non-empty values validator.types.isNonEmpty = { validate: function(value) { return value !==""; }, instructions: "the value cannot be empty" }; //check if a value is a number validator.types.isNumber = { validate: function(value){ return !isNaN(value); }, instructions: "the value can only be a valid number, e.g. 1, 3.14 or 2010" }; //checks if the value contains only letters and numbers validator.types.isAlphaNum = { validate: function(value) { return !/[^a-z0-9]/i.test(value); }, instructions: "the value can only contain characters and numbers, no special symbols" }; var validator ={ //all available checks types: {}, //error messages in teh current validation session messages: [], config: {}, //the interface method validate: function(data) { var i, msg, type, checker, result_ok; //reset all messages this.messages = []; for( i in data) { if(data.hasOwnProperty(i)){ type = this.config[i]; checker = this.types[type]; if(!type) { continue;//no need to validate } 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(); }, hasErrors: function() { return this.messages.length!==0; } }