策略模式 - Strategy

140 阅读2分钟

一、定义

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

二、核心

将算法的使用和算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成:
第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。
第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明Context 中要维持对某个策略对象的引用。

三、实现

策略模式可以用于组合一系列算法,也可用于组合一系列业务规则。

// 例如要写一个计算两个数加减乘除的方法

function countNum (type, num1, num2) {
  if (type === 'add') {
    return num1 + num2
  } else if (type === 'subtract') {
    return num1 - num2
  } else if (type === 'multiply') {
    return num1 * num2
  } else {
    return num1 / num2
  }
}
console.log(countNum('add', 9, 3))       // 12
console.log(countNum('subtract', 9, 3))  // 6
console.log(countNum('multiply', 9, 3))  // 27
console.log(countNum('', 9, 3))          // 3

作如下优化:
let calculateNum = {
  add(num1, num2) {
    return num1 + num2
  },
  subtract(num1, num2) {
    return num1 - num2
  },  multiply(num1, num2) {
    return num1 * num2  },
  divide(num1, num2) {
    return num1 / num2
  },
}

console.log(calculateNum.add(6, 2))       // 8
console.log(calculateNum.subtract(6, 2))  // 4
console.log(calculateNum.multiply(6, 2))  // 12
console.log(calculateNum.divide(6, 2))    // 3

该例子就可以看成是一个策略模式。

#又例如,商场搞促销,有部分商品打8折、部分商品打9折、满100减20、会员满100减30等活动,可以用策略模式来实现:

// 定义一个策略对象
let priceceStrategy = function() {
  // 内部算法对象 
  let strategy = {
    return20(price){
      return price - parseInt(price / 100) * 20
    },
    return30(price){
      return price - parseInt(price / 100) * 30
    },
    price80(price){
      return price  * 80 / 100
    },
    price90(price){
      return price  * 90 / 100
    }
  }
  // 策略方法调用接口
  return {
    strategyFunction(type, price) {
      return strategy[type] && strategy[type](price)
    },
    // 添加算法
    addStrategy(type, fn){
      strategy[type] = fn
    }
  }
}()

console.log(priceceStrategy.strategyFunction('return20', 200))   // 160
console.log(priceceStrategy.strategyFunction('return30', 300))   // 210
console.log(priceceStrategy.strategyFunction('price80', 100))    // 80
console.log(priceceStrategy.strategyFunction('price90', 100))    // 90
// 添加一个算法: 满100减50
priceceStrategy.addStrategy('return50', (price) => {
  return price - parseInt(price / 100) * 50
})
console.log(priceceStrategy.strategyFunction('return50', 100))  // 50

优缺点

优点:

  • 优化多重条件判断,采用策略模式是的算法更利于维护;
  • 可扩展性,策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
  • 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换。

缺点:

  • 由于选择哪种算法的决定权在用户,所以对用户来说就必须了解每种算法的实现;
  • 由于每种算法间相互独立,这样对于一些复杂的算法处理相同逻辑的部分无法实现共享,这就会造成一些资源的浪费。

跳转:设计模式目录