定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换。
问题描述:年终奖是根据员工的基本工资和年底绩效来计算的。规则如下:
- 绩效S -> 4*salary
- 绩效A -> 3*salary
- 绩效B -> 2*salary
面向过程代码如下:
var calculateBonus = function(peformanceLevel, salary) {
if(peformanceLevel === 'S') {
return 4 * salary;
}else if(peformanceLevel === 'A') {
return 3 * salary;
}else if(peformanceLevel === 'B') {
return 2 * salary;
}
};
这段代码有多个if-else,如果后期增加新的工资计算方式时,难以扩展。为了解决这个问题,我们引入策略模式,将算法的使用过和算法的实现分离开来。 一个基于策略模式的程序至少有两部分组成:第一部分是策略类,策略类封装了具体的算法,并负责具体的计算过程。 第二个部分是环境类Context, Context接受客户的请求,随后把请求委托给某一个策略类。
传统的策略模式实现如下:
// Strategy: 一系列算法,可相互替换(实现相同的接口)
var performanceS = function () {};
performanceS.prototype.calculate = function(salary) {
return salary * 4;
}
var performanceA = function () {};
performanceA.prototype.calculate = function(salary) {
return salary * 3;
}
var performanceB = function () {};
performanceB.prototype.calculate = function(salary) {
return salary * 2;
}
// Context: 客户端,委托具体的策略
var Bonus = function (salary, strategy) {
this.salary = salary;
this.strategy = strategy;
};
Bonnus.prototype.getBonus = function () {
return this.stategy.calculate(this.salary);
};
Javascript版本的实现:
var strategies = function () {
"S" : function(salary) {
return salary * 4;
},
"A" : function(salary) {
return salary * 3;
},
"B" : function(salary) {
return salary * 2;
}
};
var getBonus = function(salary, strategy) {
return strategies[strategy](salary);
};
通过策略模式,我们消除了程序中大片的if-else语句,所有跟计算相关的逻辑都不放在Context中,而是分布在各个策略中。 Context并没有计算奖金的能力,而是把这个职责委托给具体的策略类。每个策略类负责的算法被封装在各自的类中,负责完成具体的计算过程。 通过替换Context中具体的策略对象,我们便能执行不同的算法。
- 使用不同的策略实现动画(TODO)
- 表单验证(使用策略模式封装一系列业务规则,这些业务规则指向同一个目标,可以被替换)(TODO)