从计算年终奖开始,理解策略模式 - 2/14
首先,先想下怎么实现这样一个功能。
很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。
例如,绩效为 S 的人年终奖有 4 倍工资,绩效为 A 的人年终奖有 3 倍工资,而绩效为 B 的人年终奖是 2 倍工资。
假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖。
想想。。。
想想。。。
想想。。。
计算奖金--初始想法
可能多数人的第一反应是下面的
var calculateBonus = function(performanceLevel, salary) { if (performanceLevel === "S") { return salary * 4; } if (performanceLevel === "A") { return salary * 3; } if (performanceLevel === "B") { return salary * 2; } }; calculateBonus("B", 20000); // 输出:40000 calculateBonus("S", 6000); // 输出:24000
看起来完美得很。但实际有很多缺点:
- calculateBonus 函数比较庞大,包含了很多 if-else 语句,这些语句需要覆盖所有的逻辑 分支。
- calculateBonus 函数缺乏弹性,如果增加了一种新的绩效等级 C,或者想把绩效 S 的奖金系数改为 5,那我们必须深入 calculateBonus 函数的内部实现,这是违反开放 封闭原则的。
- 算法的复用性差,如果在程序的其他地方需要重用这些计算奖金的算法呢?我们的选择只有复制和粘贴。
来,再想想,怎么改进?
来,再想想,怎么改进?
来,再想想,怎么改进?
计算奖金---升级版
大逻辑:将各个评级的计算方法封装起来,然后写个对象,将评级和计算方式一一对应,使用的时候就传入评级就好。 代码如下:
var strategies = { S: function(salary) { return salary * 4; }, A: function(salary) { return salary * 3; }, B: function(salary) { return salary * 2; }, }; var calculateBonus = function(level, salary) { return strategies[level](salary); }; console.log(calculateBonus("S", 20000)); // 输出:80000 console.log(calculateBonus("A", 10000)); // 输出:30000
优点:
- 增加等级,只需在策略里增加算法就好
- 增加等级,calculateBonus函数也不需要修改
- 赏心悦目
初步理解策略模式
策略模式:封装一系列的算法,根据情况调用不同的算法,目的是将算法的实现与算法的使用分离开来,本质上就是将变与不变剥开。
拿年终奖来说:
- strategies是算法的实现,封装了一系列的算法
- calculateBonus是算法的使用
以后碰到很多if/else
的时候,想想这种改进方式。
策略模式的优缺点
优点:
- 策略模式可以有效地避免if
- 策略模式算法独立封装,易于理解和于扩展
- 算法可以复用在其他地方
缺点:封装算法和必须了解所有算法
在前面的学习中,为了清楚地表示这是一个策略模式,我们特意使用了strategies 这个名字。
如果去掉strategies,我们还能认出这是一个策略模式的实现吗?代码如下:
var S = function( salary ){ return salary * 4; }; var A = function( salary ){ return salary * 3; }; var B = function( salary ){ return salary * 2; }; var calculateBonus = function( func, salary ){ return func( salary ); }; calculateBonus( S, 10000 ); // 输出:40000
引用
- 《JavaScript的设计模式和开发实践》