设计模式之策略模式-js表单验证示例

设计模式之策略模式-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两部分代码打包为公用代码在需要的地方引用即可