1.定义
定义一系列的算法,把他们一个一个的封装起来,并且使他们可以相互替换。
2.使用策略模式计算奖金
很多公司年终奖是根据员工的基础工资以及年底绩效来发放的。例如绩效为S的人年终奖为4倍工资,绩效为A的人年终奖为3倍工资,接下来使用代码来计算员工的年终奖。
- 最初实现 实现一个calcBounds函数接受两个参数,分别为员工工资和他的绩效等级:
const calcBonus = function (performanceLevel, salary) {
if (performanceLevel === "S") {
return salary * 4;
}
if (performanceLevel === "A") {
return salary * 3;
}
};
可以发现上面的代码十分简洁但是缺点也是十分的明显:1.calcBounds函数包含很多if-else语句2.calcBounds函数缺乏弹性,如果有新的绩效那就必须更改calcBounds函数内部的代码这是违反开放-封闭原则的3.算法的复用性差。
- 使用组合函数重构
const performanceS = function (salary) {
return salary * 4;
};
const performanceA = function (salary) {
return salary * 3;
};
const calcBonus = function (performanceLevel, salary) {
if (performanceLevel === "S") {
return performanceS(salary);
}
if (performanceLevel === "A") {
return performanceA(salary);
}
};
calcBonus("A", 10000);
上面代码重构后虽然使得程序得到了改善但是还是没有解决calcBounds函数可能越来越庞大的问题
-
使用策略模式重构代码
策略模式指的是定义一系列的算法,把它们一个个封装起来。将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类 Context,Context 接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明 Context 中要维持对某个策略对象的引用。
const performanceS = function () {};
performanceS.prototype.calculate = function (salary) {
return salary * 4;
};
const performanceA = function () {};
performanceA.prototype.calculate = function (salary) {
return salary * 3;
};
//定义奖金类 Bonus:
const Bonus = function () {
this.salary = null; // 原始工资
this.strategy = null; // 绩效等级对应的策略对象
};
Bonus.prototype.setSalary = function (salary) {
this.salary = salary; // 设置员工的原始工资
};
Bonus.prototype.setStrategy = function (strategy) {
this.strategy = strategy; // 设置员工绩效等级对应的策略对象
};
Bonus.prototype.getBonus = function () {
// 取得奖金数额
return this.strategy.calculate(this.salary); // 把计算奖金的操作委托给对应的策略对象
};
const bonus = new Bonus();
bonus.setSalary(10000);
bonus.setStrategy(new performanceS()); // 设置策略对象
console.log(bonus.getBonus());
bonus.setStrategy(new performanceA()); // 设置策略对象
console.log(bonus.getBonus());
3.JAVAScript版本的策略模式
const strategies = {
S: function (salary) {
return salary * 4;
},
A: function (salary) {
return salary * 3;
},
}
const calcBonus = function (level, salary) {
return strategies[level](salary);
};
console.log(calcBonus("S", 20000));
console.log(calcBonus("A", 10000));
4.策略模式的优点
- 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
- 策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的 strategy 中,使得它们易于切换,易于理解,易于扩展。
- 策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作。
- 在策略模式中利用组合和委托来让 Context 拥有执行算法的能力,这也是继承的一种更轻便的替代方案。