《javascript设计模式与开发实践》阅读笔记(5)—— 策略模式
策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
我的理解就是把各种方法封装成函数,同时存在一个可以调用这些方法的公共函数。这样做的好处是可以消化掉内部的分支判断,使代码效率更高。
使用策略模式计算奖金
现在要实现这样一个东西,年终奖是根据员工的工资基数和年底绩效情况来发放的。例如,绩效为S的人年终奖有4倍工资,绩效为A的人年终奖有3倍工资,而绩效为B的人年终奖是2倍工资。假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖。
思路一:创建一个函数,接收两个参数,一个是绩效,一个是工资底数,然后返回年终奖
1 var calculate = function( level, salary ){ //创建了一个计算函数 2 if ( level === 'S' ){ 3 return salary * 4; 4 } 5 if ( level === 'A' ){ 6 return salary * 3; 7 } 8 if ( level === 'B' ){ 9 return salary * 2; 10 } 11 }; 12 calculate( 'B', 20000 ); // 输出:40000 13 calculate( 'S', 6000 ); // 输出:24000
这段代码的缺点很多
(1)calculate函数比较庞大,包含了很多if语句,这些语句需要覆盖所有的逻辑分支
(2)函数缺乏弹性,如果增加了一种新的绩效等级C,或者想把绩效S的奖金系数改为5,那我们必须深入calculate函数的内部实现,这是违反开放-封闭原则的。
思路二:用组合函数完成,一个函数用来计算相应奖金,另一个函数用来判断调用哪个计算函数
1 var levelS = function( salary ){ 2 return salary * 4; 3 }; 4 var levelA = function( salary ){ 5 return salary * 3; 6 }; 7 var levelB = function( salary ){ 8 return salary * 2; 9 }; 10 11 var calculate = function( level, salary ){ 12 if ( level === 'S' ){ 13 return levelS( salary ); 14 } 15 if ( level === 'A' ){ 16 return levelA( salary ); 17 } 18 if ( level === 'B' ){ 19 return levelB( salary ); 20 } 21 }; 22 23 calculate( 'A' , 10000 ); // 输出:30000
这段代码比上面的好一些,但是还是没解决关键问题,calculate函数有可能变得越来越大,而且函数依旧缺乏弹性。
思路三:策略模式,将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。
策略模式就是分成策略函数和调用函数,调用函数不应该包含分支判断,调用任何策略函数的方式应该是一致的:
1 var S=function( salary ){ 2 return salary * 4; 3 }; 4 5 var A=function( salary ){ 6 return salary * 3; 7 }; 8 9 var B=function( salary ){ 10 return salary * 2; 11 } 12 13 var calculate = function( func, salary ){ //高阶函数 14 return func( salary ); 15 }; 16 17 calculate( S, 20000 ); // 输出:80000 18 calculate( A, 10000 ); // 输出:30000
或者使用对象,让策略彼此间可以产生联系:
1 var Lv = { 2 "S": function( salary ){ 3 return salary * 4; 4 }, 5 "A": function( salary ){ 6 return salary * 3; 7 }, 8 "B": function( salary ){ 9 return salary * 2; 10 } 11 }; 12 13 var calculate = function( level, salary ){ 14 return Lv[ level ]( salary ); //这里明确只能使用Lv对象的方法,让calulate的职能更清晰,上面calulate太过通用 15 }; 16 17 calculate( 'S', 20000 ); // 输出:80000 18 calculate( 'A', 10000 ); // 输出:30000
总结
策略模式的优点:
策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展。
总结一下就是将策略函数封装,调用函数的实质就是调用这些策略函数。