今天我们来学习JavaScript常用的设计模式——策略模式

# 定义

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

把看似毫⽆联系的代码 提取封装、复⽤,使之更容易被理解和拓展。我们通过一个例子来理解一下:

# 应用场景

要完成⼀件事情,有不同的策略。例如绩效计算、 表单验证规则

计算绩效考核后的年终奖,S绩效是四个月工资,A绩效是三个月工资,B绩效是两个月工资

# 使用前

定义一个计算奖金的函数 calculateBonus ,函数入参是绩效水平和月薪

function calculateBonus(level, salary) {
  switch (level) {
    case "s": {
      return salary * 4;
    }
    case "a": {
      return salary * 3;
    }
    case "b": {
      return salary * 2;
    }
    default: {
      return 0;
    }
  }
};

计算奖金

calculateBonus('s', 10000); // 40000
calculateBonus('a', 5000); // 15000

如果我们要修改绩效规则,就需要更改calculateBonus函数中的逻辑,违背了开放封闭原则,此时就可以考虑使用策略模式。

# 改进

将逻辑都解耦出来

function getS(salary){
  return salary * 4
}
function getA(salary){
  return salary * 3
}
function getB(salary){
  return salary * 2
}

function calculateBonus(level, salary) {
  switch (level) {
    case "s": {
      return getS(salary);
    }
    case "a": {
      return getA(salary);
    }
    case "b": {
      return getB(salary);;
    }
    default: {
      return 0;
    }
  }
};

这样还是很多逻辑判断,我们可以需要构建一个映射关系,构建一个绩效规则的策略表

# 使用策略模式

使用JavaScript中的 对象映射 构造一个策略表

const strategies = {
  s: (salary) => {
    return salary * 4;
  },
  a: (salary) => {
    return salary * 3;
  },
  b: (salary) => {
    return salary * 2;
  },
};

定义计算奖金的函数,函数入参是绩效水平和月薪,然后去策略表中查找绩效奖金的规则。

function calculateBonus(level, salary) {
  return strategies[level](salary);
};

最后就可以使用这个策略模式。使用其中某个绩效计算算法的时候,直接通过标签名去定位就可以了。

calculateBonus('s', 10000); // 40000
calculateBonus('a', 5000); // 15000

我们再看看策略模式的定义:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

PS: 这里的相互替换实际上是针对静态类型语言而言的。静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。只有把真正的类型隐藏在接口后时,它们才能被相互替换。而在JavaScript这种弱类型的语言中,任何对象都可以被替换使用。因此,在JavaScript中的“相互替换”可以理解为具有相同的目标和意图。

上次更新: 2022/4/18 18:10:13