今天我们来学习JavaScript常用的设计模式——策略模式
# 定义
定义⼀系列的算法,把它们⼀个个封装起来,并且使它们可以相互替换。
把看似毫⽆联系的代码 提取封装、复⽤,使之更容易被理解和拓展。我们通过一个例子来理解一下:
# 应用场景
要完成⼀件事情,有不同的策略。例如绩效计算、 表单验证规则
计算绩效考核后的年终奖,S
绩效是四个月工资,A
绩效是三个月工资,B
绩效是两个月工资
# 使用前
定义一个计算奖金的函数 calculateBonus
,函数入参是绩效水平和月薪
function calculateBonus(level, salary) {
switch (level) {
case "s": {
return salary * 4;
}
case "a": {
return salary * 3;
}
case "b": {
return salary * 2;
}
default: {
return 0;
}
}
};
计算奖金
calculateBonus('s', 10000); // 40000
calculateBonus('a', 5000); // 15000
如果我们要修改绩效规则,就需要更改calculateBonus
函数中的逻辑,违背了开放封闭
原则,此时就可以考虑使用策略模式。
# 改进
将逻辑都解耦出来
function getS(salary){
return salary * 4
}
function getA(salary){
return salary * 3
}
function getB(salary){
return salary * 2
}
function calculateBonus(level, salary) {
switch (level) {
case "s": {
return getS(salary);
}
case "a": {
return getA(salary);
}
case "b": {
return getB(salary);;
}
default: {
return 0;
}
}
};
这样还是很多逻辑判断,我们可以需要构建一个映射关系,构建一个绩效规则的策略表
# 使用策略模式
使用JavaScript中的 对象映射
构造一个策略表
const strategies = {
s: (salary) => {
return salary * 4;
},
a: (salary) => {
return salary * 3;
},
b: (salary) => {
return salary * 2;
},
};
定义计算奖金的函数,函数入参是绩效水平和月薪,然后去策略表中查找绩效奖金的规则。
function calculateBonus(level, salary) {
return strategies[level](salary);
};
最后就可以使用这个策略模式。使用其中某个绩效计算算法的时候,直接通过标签名去定位就可以了。
calculateBonus('s', 10000); // 40000
calculateBonus('a', 5000); // 15000
我们再看看策略模式的定义:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
PS: 这里的相互替换
实际上是针对静态类型语言而言的。静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。只有把真正的类型隐藏在接口后时,它们才能被相互替换。而在JavaScript
这种弱类型的语言中,任何对象都可以被替换使用。因此,在JavaScript中的“相互替换”可以理解为具有相同的目标和意图。