什么是策略模式

定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类context,context接受客户的请求,随后把请求委托给某一个策略类。

策略模式可以消除程序中大片的条件分支语句。

面向对象例子:

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
class LevelA{
calculate(salary) {
return salary * 2;
}
}

class LevelB{
calculate(salary) {
return salary * 3;
}
}

class LevelC{
calculate(salary) {
return salary * 4;
}
}

export class GetBonus{
constructor() {
this.calculateMapping = {
A: new LevelA(),
B: new LevelB(),
C: new LevelC()
}
}

calculate(type, salary) {
return this.calculateMapping[type].calculate(salary);
}
}

函数式例子:

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
* 使用策略模式实现表单验证
*/

(function () {

var strategies = {
isNotEmpty: function (value, errorMsg) {
if (value === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) {
if (value.length < length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) {
if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
return errorMsg;
}
},
isNumber: function (value, errorMsg) {
if (isNaN(Number(value))) {
return errorMsg;
}
}
};

var registerForm = document.querySelector('form');

var Validator = function () {
this.cache = [];
};

Validator.prototype.add = function (dom, rule, errorMsg) {
var arr = rule.split(':');
this.cache.push(function () {
var strategy = arr.shift();
arr.unshift(dom.value);
arr.push(errorMsg);
return strategies[strategy].apply(dom, arr)
});
};

Validator.prototype.start = function () {
for (var i = 0, len = this.cache.length; i < len; i++) {
var msg = this.cache[i]();
if (msg) {
return msg;
}
}
};

var validataFunc = function () {
var validator = new Validator();
validator.add(registerForm.number, 'isNotEmpty', '数量不能为空');
validator.add(registerForm.number, 'isNumber', '请输入数字');
validator.add(registerForm.number, 'minLength:2', '数量至少要2位字符');
var errorMsg = validator.start();
return errorMsg;
};

var init = function () {
document.querySelector('.submitBtn').onclick = function () {
var errorMsg = validataFunc();
if (errorMsg) {
alert(errorMsg);
} else {
Event.trigger('draw-circle', {number: registerForm.number.value});
}
};
};

init();

})();