JavaScript设计模式—策略模式

定义

定义一系列算法,把它们一个个封装起来,而且使它们能够相互替换。一个基于策略模式的程序至少有两部分组成:web

  1. 策略类:封装具体的算法,并负责具体的计算过程
  2. 环境类 Context: Context接受客户请求,随后将请求委托给策略类

真实世界类比

策略模式

假如你须要前往机场。 你能够选择乘坐公共汽车、 预定出租车或骑自行车。 这些就是你的出行策略。 你能够根据预算或时间等因素来选择其中一种策略。算法

模式实现-计算奖金

这里咱们以年终奖的计算为例进行实现:设计模式

假设绩效为S的人年终奖有 4 倍工资;A的人年终奖有 3 倍工资;B的人年终奖有 2 倍工资。markdown

按照策略模式的基本组成咱们进行分解:app

// 第一步: 封装策略类
const strategies = {
  S: salary => {
    return salary * 4;
  },
  A: salary => {
    return salary * 3;
  },
  B: salary => {
    return salary * 2;
  }
};

// 第二步:这里咱们用calculateBonus函数充当Context来接收用户请求
const calculateBonus = (level, salary) => {
  return strategies[level](salary);
};

console.log(calculateBonus("S", 20000)); // 输出:80000
console.log(calculateBonus("A", 10000)); // 输出:30000
复制代码

更广义的“算法”

策略模式指的是定义一系列算法。但在实际的开发中,咱们一般会把算法的含义扩散开来,使策略模式也能够用来封装一系列的业务规则。只要这些业务规则指向的目标一致,并且能够被替换使用。dom

模式实现-表单校验

在 web 应用中,涉及表单的部分几乎都离不开校验。函数

假设咱们正在编写一个注册页面,在点击注册按钮前,须要校验如下几条逻辑:oop

  • 用户名不能为空
  • 密码长度很多于 6 位
  • 手机号必须符合格式
// 第一步: 封装策略类
const strategies = {
  isNonEmpty: (value, errorMsg) => {
    if (value === "") {
      return errorMsg;
    }
  },
  minLength: (value, errorMsg) => {
    if (value.length < 6) {
      return errorMsg;
    }
  },
  isMobile: (value, errorMsg) => {
    if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
      return errorMsg;
    }
  }
};

// 第二步:封装Validator类充当Context来接收用户请求并委托给strategy对象
class Validator {
  constructor() {
    this.cache = [];
  }
  add(dom, strategy, errorMsg) {
    this.cache.push(() => {
      const args = [dom.value, errorMsg];
      return strategies[strategy].apply(dom, args);
    });
  }
  start() {
    this.cache.forEach(fn => {
      const msg = fn();
      if (msg) {
        return msg;
      }
    });
  }
}

// 使用
const registerForm = document.getElementById("registerForm");
function validataFunc() {
  const validator = new Validator();
  validator.add(registerForm.userName, "isNonEmpty", "用户名不能为空");
  validator.add(registerForm.password, "minLength", "密码长度不能少于6位");
  validator.add(registerForm.phone, "isMobile", "手机号码格式不正确");
  const error = validator.start();
  return error;
}
registerForm.onsubmit = () => {
  const errorMsg = validataFunc();
  if (errorMsg) {
    alert(errorMsg);
    return false;
  }
};
复制代码

能够看到,咱们仅仅经过配置的方式就完成了一个表单的校验。this

小结

在JavaScript语言的策略模式中,策略类每每被函数所代替,这时策略模式就成了一种“隐形”的模式。尽管如此,从根本上理解策略模式的理念不只让咱们对模式有这更透彻的了解,也能够让咱们明白使用函数的好处。spa

参考

相关文章
相关标签/搜索