策略模式支持我们在运行的时候选择算法。代码的客户端可以使用同一个接口来工作,但是它却根据客户端正在试图执行任务的上下文,从多个算法中选择用于处理特定任务的算法。
使用策略模式的其中一个例子是解决表单验证的问题。可以创建一个具有validate()方法的验证器对象。无论表单的具体类型是什么,该方法都将会被调用,并且返回相同的结果,一个未接验证的数据列表以及任意的错误信息。
但是根据具体的表单形式以及待验证的数据,验证器客户端可能选择不同类型的检查方法。验证器将选择最佳的策略以处理任务,并且将具体的数据验证委托给适当的算法。
数据验证示例
假设有以下数据块,它可能来自于网页的一个表单,需要验证是否有效:
var data = {
fisrt_name: "Super",
last_name: "Man",
age: "unknown",
username: "o_0"
};
在这个具体的例子中,为了使验证器知道什么是最好的策略,首先需要配置验证器,并且设置认为是有效的且可接受的规则。
假如在表单验证中,对于姓氏不做要求,但是对于年龄必须要求为数字,并且用户中仅出现字母和数字且无特殊字符。该配置要求如下:
validator.config={
first_name:"isNonEmpty",
age:"isNumber",
username:"isAlphaNum"
}
现在,validator对象已经配置完毕并可用于数据处理,可以调用validator对象的valiadte()方法,并将错误信息打印到控制台:
valiadtor.validate(data);
if(valiadtor.hasErrors()){
console.log(valiadtor.message.join("\n"));
}
现在,让我们看看验证程序是如何实现validator对象的。用于检查的可用算法也是对象,他们具有一个预定义的接口,提供了一个validate()方法和一个用于提示错误消息的一行帮助信息。
var validator={
//所有可用的检查
types : {},
//错误消息
messages:[],
//当前验证配置
config: {},
//接口方法
validate:function (data){
var i, msg, type, checker, result_ok;
this.messages = [];
for(i in data){
if(data.hasOwnProperty(i)){
type = this.config[i];
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 = "Invalidate value for *" + i +"*,"+ checker.instructions;
this.messages.push(msg);
}
}
}
return this.hasErrors();
},
hasErrors:function () {
return this.messages.length !== 0;
}
}
validator.types.isNonEmpty = {
validate: function (value) {
return value !== "";
},
instructions:"the value cannot be empty"
};
validator.types.isNumber = {
validate: function(value){
return !isNaN(value);
},
instructions:"the value can only be a vaild number"
};
validator.types.isAlphaNumer = {
validate: function (value){
return !/[^a-z0-9]/i.test(value);
},
instructions:"the value can only contain characters and numbers"
};
var data = {
first_name:"kong",
last_name:"chao",
age:"unknown",
username:"o_0"
};
validator.config = {
fist_name:"isNonEmpty",
age : "isNumber",
username : "isAlphaNumer"
}
validator.validate(data);
if(validator.hasErrors()){
console.log( validator.messages.join("\n"));
}
validator对象是通用的,可以将其保存起来以用于验证用例。