定义
策略模式的定义是定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
越狱相信大部分都看过,第一部剧中迈克尔设计了两条通往医务室的道路。国庆节、春节回家的方式很多种,我们可以选择飞机、高铁,还可以坐火车、大巴车。
作用
策略模式最主要的作用是在我们想找一种方式替换太多if else的条件语句,因为条件语句会让程序难以维护,且违反开放-封闭原则。
举例
根据模式的作用,我们来举例:
var calculateBonus = function (performanceLevel, salary) {
if (performanceLevel === 'S') {
return salary * 4;
}
if (performanceLevel === 'A') {
return salary * 3;
}
if (performanceLevel === 'B') {
return salary * 2;
}
};
// test
calculateBonus('B', 20000); // 40000
calculateBonus('A', 6000); // 18000
上面的代码就是我们一开始说的,太多if else条件判断语句,且我们想增加第四种模式,比如'C'时,我们需要修改代码内部,添加如下代码:
if (performanceLevel === 'C') {
return salary;
}
最后这个calculateBonus会多么庞大,想想就恶心。下面我们使用策略模式来重构一下代码,模式的目的就是讲算法的使用与算法的实现分离开来。
一个策略模式的程序至少由两部分组成。第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类context,Context接受客户的请求。随后把请求委托给某一个策略类。
var performanceS = function () {};
performanceS.prototype.calculate = function (salary) {
return salary * 4;
};
var performanceA = function () {};
performanceS.prototype.calculate = function (salary) {
return salary * 3;
};
var performanceB = function () {};
performanceS.prototype.calculate = function (salary) {
return salary * 2;
};
var Bonus = function () {
this.salary = null; // 原始工资
this.strategy = null; // 绩效等级对应的策略对象
};
Bonus.prototype.setSalary = function (salary) {
this.salary = salary; // 设置员工的原始工资
};
Bonus.prototype.setStrategy = function (salary) {
this.strategy = strategy ; // 设置员工绩效等级对应的策略对象
};
Bonus.prototype.getBonus = function () { // 取得奖金数额
return this.strategy.calculate(this.salary); // 把计算奖金的操作委托给对应的策略对象
};
测试代码:
var bonus = new Bonus();
bonus.setSalary(10000);
bonus.setStrategy(new PerformanceS());
console.log(bonus.getBonus()); // 40000
bonus.setStrategy(new PerformanceA());
console.log(bonus.getBonus()); // 30000
上面的重构代码利用传统的OOP,在JS中,这个重构方式显得太笨拙了。函数也是对象,我们更直接和简洁的做法是把strategy直接定义为函数:
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
策略模式在前端开发中更常见的使用时封装表单校验。
优点
- 策略模式提供了对“开放-封闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
- 策略模式提供了管理相关的算法族的办法。
- 策略模式提供了可以替换继承关系的办法。
- 使用策略模式可以避免使用多重条件转移语句。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
小结
本文通过提供接近传统面向对象语言的策略模式,也提供了更适合Javascript语言的策略模式版本。在Javascript语言的策略模式中,策略类往往被函数所替代,这时策略模式就成为一种“隐形”的模式。
系列文章关注博客!