Javascript设计模式之策略模式

·  阅读 358

策略模式

定义

定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

策略模式的实现

先来考虑这么一个问题,根据员工的绩效和基本工资去计算每个人的奖金数额。

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
复制代码

这个代码很简单,但是有以下几个问题。

  1. 代码if else 语句过多,这些语句需要覆盖所有的逻辑分支。
  2. 函数时刻需要修改,如果引进C级别绩效,就需要修改函数。
  3. 算法复用性差。

我们用策略模式去重构代码:

下面的代码我不详细说明了,具体来说是声明了策略方法,而在新建对象时传入对应的策略。代码的逻辑很清晰,但是写起来非常复杂。原因是下面的代码是javascript本身在模拟其他传统的面向对象语言实现。

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;
};
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); // 把计算奖金的操作委托给对应的策略对象
};
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
复制代码

javascript版本的策略模式

代码非常的简单与精炼,我们直接把策略当成一个对象,键值对分别是策略的名称,以及策略的实现。然后我们要使用对应的策略只需要传入不同的函数即可。

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
复制代码

如果想要添加策略,只需要给对象赋键值对即可,非常简单的实现的策略模式的思想。

strategies.C = function(){}
复制代码

这样一来,我们不需要去修改原本函数,而是增加函数,在需求发生变化的时候不需要去阅读他人的源码,在他人代码上进行修改,而是直接自己增加配置,这样的好处不言而喻。(修改别人代码当然还要考虑是否影响别的功能,提高了维护成本。)

总结

总结就用书里的话来结尾吧:

Peter Norvig 在他的演讲中曾说过:“在函数作为一等对象的语言中,策略模式是隐形的。strategy 就是值为函数的变量。”在 JavaScript 中,除了使用类来封装算法和行为之外,使用函数 当然也是一种选择。这些“算法”可以被封装到函数中并且四处传递,也就是我们常说的“高阶函数”。实际上在 JavaScript 这种将函数作为一等对象的语言里,策略模式已经融入到了语言本身当中,我们经常用高阶函数来封装不同的行为,并且把它传递到另一个函数中。当我们对这些函数发出“调用”的消息时,不同的函数会返回不同的执行结果。在 JavaScript 中,“函数对象的多态性”来得更加简单。

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改