# JS设计模式-策略模式

策略模式:定义一系列的算法,把他们一个个封装起来,并让它们可以相互替换。

# 场景

策略模式的应用场景有许多,比如:网吧会员的计算系统,还有电商的优惠方式等等。在这里,我就用公司旁边那家网吧的计费方式为事例进行解析。

网吧的计费规则是这样的:(网费为5块一小时)

  • 普通VIP,8折优惠
  • 白银VIP,6折优惠
  • 白银VIP,5折优惠

# 实现

我们很容易写下如下代码:

function calcPrice(level, price) {
  if(level === 'VIP') {
    return price * 0.8
  }
  if(level === 'silverVIP') {
    return price * 0.6
  }
  if(level === 'goldVIP') {
    return price * 0.5
  }
  return price
}
calcPrice('VIP', 50)  		  // 返回 40
calcPrice('silverVIP', 50)  // 返回 30

我们来看一下上面的代码,总结一下有以下几个缺点:

  • if判断太多,影响函数的执行效率。(在这个函数,效率影响的可能没有那么明显)
  • 如果我们再添加一种会员机制,比如:超级会员打4折。我们需要到calcPrice函数内部去修改,这个违反了开放-封闭原则

# 改进

对于第一个缺点,我们可以使用switch case这个语法糖进行改写一下,得到如下代码:

function calcPrice(level, price) {
   switch (level) {
    case 'VIP':
      return price * 0.8
    case 'silverVIP':
      return price * 0.6
    case 'goldVIP':
      return price * 0.5
    default:
      return price
  }
}

对于第二个缺点,我们就需要今天的主角,策略模式去修改了

# 写法一

var strategies = {
  'VIP': function (price) {
    return price * 0.8
  },
  'silverVIP': function (price) {
    return price * 0.6
  },
  'goldVIP': function (price) {
    return price * 0.5
  },
}
function calcPrice(level, price) {
    return strategies[level](price)
}

console.log(calcPrice('VIP', 50)) // 40

# 写法二

我们注意到上面代码,将所有的策略封装到一个对象中,也可以直接写成函数的形式。

function nVip(price) {
  return price * 0.8
}

function silverVIP(price) {
  return price * 0.6
}

function goldVIP(price) {
  return price * 0.5
}

function calcPrice(fn, price) {
  return fn(price)
}

console.log(calcPrice(nVip, 50))

注意方法二里面的VIP函数我加了一个小写的n变成nVip 主要原因是因为,函数类名需要大写。这点大家注意一下!

我个人比较偏爱方法一的实现,因为方法二产生了大量的函数名。浪费命名空间。

# 总结

  • 策略模式能有有效避免多重判断,提升效率
  • 做到了开放-封闭原则,由于策略定义在函数外面,易于扩展 切换和阅读
  • 策略模式需要使用者知道很多,才能做好决策。这是一个小小的遗憾

# 拓展

其实,我们在表单验证的时候,会使用到大量的校验规则,我们这策略模式能够很好的管理起校验规则。有兴趣的同学可以去实现一下:

  • 用户名不能为空,大于6个字符小于10个字符
  • 密码长度大于6
  • 手机号验证

我稍后会把,实现的代码放到我的官网,有兴趣的同学可以自取。

点击阅读原文 就可以访问我的小站了。

下一讲:我们一起来学习 单例模式

关注公众号
组队学习,一同成长
扫码添加好友
备注 加群学习