策略模式支持我们在运行的时候选择算法。代码的客户端可以使用同一个接口来工作,但是它却根据客户端正在试图执行任务的上下文,从多个算法中选择用于处理特定任务的算法。
使用策略模式的其中一个例子是解决表单验证的问题。可以创建一个具有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")); }
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")); }