一句话概括,定义一堆行为(策略类),再用一个函数统筹(环境类),调用这些行为。
就用个对象包裹着不同行为策略,再通过一个函数去使用这些策略。
const strategies = { add: function(num1, num2){ return num1 + num2; }, subtract: function(num1, num2){ return num1 - num2; }, multiply: function(num1, num2){ return num1 * num2; }, divide: function(num1, num2){ return num1 / num2; }, } const calcRes = function(type, num1, num2){ return strategies[type](num1, num2); } console.log(calcRes('add', 1, 2)); // 3 console.log(calcRes('multiply', 1, 2)); // 2
比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; } }; calculateBonus( 'B', 20000 ); // 输出:40000 calculateBonus( 'S', 6000 ); // 输出:24000
正常可能会这么写,if-else。 但是这种写法是有缺点的。
calculateBonus 函数比较庞大,包含了很多 if-else 语句
calculateBonus 函数缺乏弹性,如果增加了一种新的绩效等级 C,或者想把绩效 S 的奖金 系数改为 5,那我们必须深入 calculateBonus 函数的内部实现,这是违反开放封闭原则的。
算法的复用性差
若用策略模式的思维加以重构:
class BonusStrategy { calculate(salary) { // 策略接口中的默认实现 return 0; } } class SPerformanceStrategy extends BonusStrategy { calculate(salary) { return salary * 4; } } class APerformanceStrategy extends BonusStrategy { calculate(salary) { return salary * 3; } } class BPerformanceStrategy extends BonusStrategy { calculate(salary) { return salary * 2; } } const calculateBonus = function (performanceLevel, salary) { const strategies = { S: new SPerformanceStrategy(), A: new APerformanceStrategy(), B: new BPerformanceStrategy(), }; const strategy = strategies[performanceLevel]; if (strategy) { return strategy.calculate(salary); } return 0; // 默认情况 }; console.log(calculateBonus('S', 1000)); // 输出: 4000 console.log(calculateBonus('A', 1000)); // 输出: 3000 console.log(calculateBonus('B', 1000)); // 输出: 2000
但是在js中,不一定是要用这种class形式写,才叫策略模式。这种模式 在后端语言中比如java 可能会经常用到,但是在js中,往往有更为明了的策略模式写法。把策略类弄成对象的形式,因为在js中,function 也是 Object 对象类型。
var strategies = { S: function (salary) { return salary * 4; }, A: function (salary) { return salary * 3; }, B: function (salary) { return salary * 2; }, }; var calculateBonus = function (performanceLevel, salary) { var strategy = strategies[performanceLevel]; if (strategy) { return strategy(salary); } return 0; // 默认情况 }; console.log(calculateBonus('S', 1000)); // 输出: 4000 console.log(calculateBonus('A', 1000)); // 输出: 3000 console.log(calculateBonus('B', 1000)); // 输出: 2000
使用函数的方式可以更简洁地定义策略,并且不需要使用类和继承的概念。