本系列为《JavaScript设想形式与开辟实践》(作者:曾探)进修总结,如想深切相识,请支撑作者原版
战略形式
战略形式
的定义:定义一系列的算法,把它们一个个封装起来,而且使它们能够相互替换。
举个抽象的例子,运用战略形式盘算奖金
。
营业需求:
绩效为
S
的人年终奖有4倍
工资绩效为
A
的人年终奖有3倍
工资绩效为
B
的人年终奖有2倍
工资
财务部愿望我们能够供应一段代码,轻易他们盘算员工的年终奖。
最初的代码完成
我们能够编写一个名为calculateBonus
的函数来盘算员工的奖金数额,这个函数须要传入两个参数:工资数额
和绩效品级
。代码以下:
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语句,这些语句须要掩盖一切的逻辑分支
calculateBonus
函数缺少弹性
,假如增添新的绩效品级,那我们必需深切calculateBonus
内部,违反了开放-关闭
准绳算法的
复用性
差,假如在顺序的其他地方须要重用这些盘算奖金的算法,我们的挑选只要复制和粘贴
因而,我们要重构
这段代码。
运用组合函数重构代码
我们把种种算法封装到一个个小函数
内里:
var performanceS = function(salary) {
return salary * 4;
}
var performanceA = function(salary) {
return salary * 3;
}
var performanceB = function(salary) {
return salary * 2;
}
var calculateBonus = function(performanceLevel, salary) {
if (performanceLevel == 'S') {
return performanceS(salary);
}
if (performanceLevel == 'A') {
return performanceA(salary);
}
if (performanceLevel == 'B') {
return performanceB(salary);
}
};
calculateBonus('A', 10000);//输出:30000
我们的顺序得到了肯定的改良,但我们依旧没有解决最主要的问题:calculateBonus
函数有能够越来越庞大,而且在系统变化的时候缺少弹性。
运用战略形式重构代码
将稳定的部份和变化的部份离隔是每一个设想形式的主题
,战略形式也不破例,战略形式的目标就是将算法的运用与算法的完成星散开来
。
一个基于战略形式的顺序最少由两部份构成,第一部份是一组战略类,战略类封装了细致的算法,并担任细致的盘算历程。第二部份是环境类Context接收客户的要求,随后把要求托付给某一个战略类。
如今我们用战略形式来重构上边的代码。
//我们先把每种绩效的盘算划定规矩封装在对应的战略类里
var porformanceS = function() {};
porformanceS.prototype.calculate = function(salary) {
return salary * 4;
};
var porformanceA = function() {};
porformanceA.prototype.calculate = function(salary) {
return salary * 3;
};
var porformanceB = function() {};
porformanceB.prototype.calculate = function(salary) {
return salary * 2;
};
//接下来定义奖金类Bonus:
var 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);
}
在完成最终的代码之前,我们再来回顾一下战略形式的头脑
:
定义一系列的算法,把它们一个个封装起来,并且使它们能够相互替换。
假如说的更细致一点,就是:定义一系列的算法,把它们各自封装成战略类,算法被封装在战略类内部的要领里。在客户对Context提议要求的时刻,Context老是把要求托付给这些战略对象中的某一个举行盘算。
我们继承完成适才的代码:
var Bonus = new Bonus();
bonus.setSalary(1000);
bonus.setStrategy(new performanceS());
bonus.getBonus();
JavaScript版本的战略形式
上述代码是模拟了一些传统的面向对象言语的完成,实际上在JavaScript
中,函数也是对象,所以更简朴和直接的做法是把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);
};
总结
在JavaScript言语中,战略类
每每被函数所替换,这是战略形式就成为了一种隐形
的形式。只管如许,完全相识战略形式,也有助于我们邃晓运用函数的优点。