JavaScript设计模式(三) - 策略模式
什么是策略模式?
策略模式支持在运行时由使用者选择合适的算法,对于使用者而言不用关心背后的具体实现,由使用者自动根据当前程序执行的上下文和配置,从已有的算法列列表中选择出合适的算法来处理当前任务。
上面的两个例子就是策略模式,比如根据选择的刷子的种类不同,我们可以刷出不同样式的线条出来,但是各种刷子背后的实现机制我们并不需要关心,我们只需要关心当前图中需要应用哪种刷子可以完成任务。 商品类似。
为什么要使用策略模式?
通过使用策略模式,我们可以很好地解决调用和需要调用的算法的耦合、增强可扩展性、可维护性等。
如何实现策略模式?
对于策略模式,最为常用的场景就是 --- 表单验证。
通常对于一个表单,各个字段的输入值可能格式不一,电话号码、密码、邮箱,使用数字、字符等等,多个字段还要验证非空,一般而言,我们的实现方式可能是十几个甚至几十、上百个if、else,但是这样看上去验证函数会非常冗余。 这时,我们可以吧常见的验证策略抽象为一个策略集合,使用者需要对表单数据进行校验时,只需要传入数据以及指定各个字段的验证策略,就可以给出相应的验证结果了。
我们期望这样的调用:
// 待校验的数据 var data = { name: ' 王 x', gender: 1, identity: '011110198806061234', birthday: '1988-13-01', mobile: '15800000000', spareMobile: '13911111111', email: 'abcdef.cn' }; // 校验规则配置 validator.config = { name: { text: ' 姓名 ', validators: ['isNotEmpty', 'isValidName'] }, identity: { text: ' 身份证号 ', validators: ['isNotEmpty','isValidIdentity'] }, birthday: { text: ' 生日 ', validators: [['isBirthEqualTo','identity'],'isValidDate'] }, mobile: { text: ' 手机号码 ', validators: ['isValidMobile'] }, spareMobile: { text: ' 备用手机号码 ', validators: ['isValidMobile', ['isNotEqualTo', 'mobile']] }, email: { text: 'Email', validators: ['isValidEmail'] } }; // 调用获得校验结果 validator.validate(data); if(validator.hasErrors()){ validator.messages.join('<br/>'); } // 期望结果: /* 姓名只能为 2-4 个字的汉字 生日与身份证号不一致,请修改 生日格式不合法,请按 "2008-01-01" 格式输入日期 备用手机号码不得与手机号码相同,请重新输入 Email 格式不合法,请输入正确的 Email 地址 */
那么,下面我们就看看如何实现这样的validator对象 --- 针对每种校验策略,我们需要指定校验方法和校验失败时的错误提示,这些策略可以挂载到validator对象内部方便管理:
// 所有可用的校验 validator.types = { isNotEmpty: { validate: function(value){ return value !== ""; }, message: " 不得为空 " }, isNotEqualTo: { validate: function(data, curField, compareField){ return data[curField] === data[compareField]; }, message: function(fieldText){ return " 不得与 " + fieldText + " 相同,请重新输入 "; } }, isValidName: { validate: function(value){ return /^[\u4e00-\u9fa5]{2,4}$/.test(value); }, message: " 只能为 2-4 个字的汉字 " }, ... };
这样,以后,每次出现了需要验证的新的策略,我们就只需要将之添加到validator.types下面,然后在validator.config中添加校验规则,代码其他部分就不需要再进行调整了,依然执行validator.validate方法。