设计模式之策略模式-js表单验证示例
策略模式
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。下面就以一个示意性的实现讲解策略模式实例的结构。
需求:
对已封装请假表单的对象obj 验证输入值是否合法
1. 策略类 表单值处理验证逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| var strategies = { "isNonEmpty": function(value, errorMsg) { if (value === '') { return errorMsg; } }, "minLength": function(value, length, errorMsg) { if (value.length < length) { return errorMsg; } }, "maxLength": function(value, length, errorMsg) { if (value || value.length > length) { return errorMsg; } }, "isMobile": function(value, errorMsg) { if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) { return errorMsg; } }, "isFormatDT": function(value, errorMsg) { var nStartTime = Number(fBuildTime_S(value)); if (nStartTime == NaN) { return errorMsg; } }, "dateOrder": function(value, errorMsg) { var valueArr = value.split(":"); var startTime = valueArr[0]; var endTime = valueArr[1]; var nStartTime = Number(fBuildTime_S(startTime)); var nEndTime = Number(fBuildTime_S(endTime)); if (nStartTime > nEndTime) { return errorMsg; } } };
var fBuildTime_S = function(time) { if (!time) { return null; } var toSaveTime = replaceNoDigit(time); var len = toSaveTime.length; if (len < 14) { toSaveTime += "000000"; } return toSaveTime; }
|
验证器类 用来操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| var Validator = function() { this.cache = []; };
Validator.prototype.add = function(value, rules) { var self = this; for (var i = 0, rule; rule = rules[i++];) { (function(rule) { var strategyAry = rule.strategy.split(':'); var errorMsg = rule.errorMsg; self.cache.push(function() { var strategy = strategyAry.shift(); strategyAry.unshift(value); strategyAry.push(errorMsg); return strategies[strategy].apply(value, strategyAry); }); })(rule) } }; Validator.prototype.start = function() { for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) { var msg = validatorFunc(); if (msg) { return msg; } } };
|
使用时 我们通过Validator的两个方法来添加和开始校验
- add() //添加校验逻辑
- start() //开始校验
使用验证器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| function fValidateInput_O(obj){ var validator = new Validator(); validator.add(obj.leaveType,[{ strategy:"isNonEmpty", errorMsg:"请选择请假类别!" }]); validator.add(obj.leaveReason,[{ strategy:"isNonEmpty", errorMsg:"请假事由不可为空!" }]); validator.add(obj.leaveTo,[{ strategy:"isNonEmpty", errorMsg:"去向不可为空! " }]); validator.add(obj.leaveContact,[{ strategy:"isNonEmpty", errorMsg:"联系方式不可为空! " }]); validator.add(obj.leaveContact,[{ strategy:"isNonEmpty", errorMsg:"联系方式不可为空! " }]); validator.add(obj.leaveFromDate,[{ strategy:"isNonEmpty", errorMsg:"请假开始时间不可为空! " }]); validator.add(obj.leaveToDate,[{ strategy:"isNonEmpty", errorMsg:"请假结束时间不可为空! " }]); validator.add(obj.leaveFromDate,[{ strategy:"isFormatDT", errorMsg:"请假开始时间格式不正确! " }]); validator.add(obj.leaveToDate,[{ strategy:"isFormatDT", errorMsg:"请假结束时间格式不正确! " }]); validator.add(obj.leaveFromDate+":"+obj.leaveToDate,[{ strategy:"dateOrder", errorMsg:"请假结束时间应该晚于开始时间! " }]); var errorMsg = validator.start(); return !errorMsg? true:layerCommonUtil.error(errorMsg); }
|
总结
- strategies 策略类我们将来可以完善更新并重复使用,如果遇到相同的验证逻辑不必再重新编写代码
- Validator 验证器类,除非优化,基本以后不必修改,可以重复使用
- fValidateInput_O 使用方法中我们只需要根据实际需要修改我们的add()验证逻辑即可
使用中,我们建议可以把strategies和Validator两部分代码打包为公用代码在需要的地方引用即可