欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js 设计模式——策略模式

程序员文章站 2024-01-11 22:49:58
策略模式(Strategy) 定义:将定义的一组算法封装起来,使其相互之间可以替换。封装的算法具有一定的独立性,不会随客户端的变化而变化 废话不多说,先来个例子 上面的例子,一定会有人这么写的,你要说没有我也没办法(~ ̄▽ ̄)~,这样写首先不利于维护,其实也不好方便扩展 改进一下: 上面的例子就可以 ......

策略模式(strategy)

定义:将定义的一组算法封装起来,使其相互之间可以替换。封装的算法具有一定的独立性,不会随客户端的变化而变化

废话不多说,先来个例子

// 例如要写一个计算两个数加减乘除的方法,会有人这么写
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
  }
}

countnum('add', 9, 3)       // 12
countnum('subtract', 9, 3)  // 6
countnum('multiply', 9, 3)  // 27
countnum('', 9, 3)          // 3

上面的例子,一定会有人这么写的,你要说没有我也没办法(~ ̄▽ ̄)~,这样写首先不利于维护,其实也不好方便扩展

改进一下:

let countnum = {
  add(num1, num2) {
    return num1 + num2
  },
  subtract(num1, num2) {
    return num1 - num2
  },
  multiply(num1, num2) {
    return num1 * num2
  },
  divide(num1, num2) {
    return num1 / num2
  },
}

countnum.add(9, 3)      // 12
countnum.subtract(9, 3) // 6
countnum.multiply(9, 3) // 27
countnum.divide(9, 3)   // 3

上面的例子就可以看成是一个策略模式

now,现在有个需求,快要圣诞节,所以咧,超市中一部分商品8折出售,一部分9折出售,等到元旦还要搞大事,普通用户满100返30,vip用户满100返50,用策略模式来实现

// 定义一个策略对象
let pricecestrategy = function(){
  // 内部算法对象 
  let strategy = {
    return30(price){
      return price + parseint(price / 100) * 30
    },
    return50(price){
      return price + parseint(price / 100) * 50
    },
    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
    }
  }
}()

pricecestrategy.strategyfunction('return30', 100)   // 130
pricecestrategy.strategyfunction('return50', 100)   // 150
pricecestrategy.strategyfunction('price80', 100)    // 80
pricecestrategy.strategyfunction('price90', 100)    // 90
// 添加一个算法
pricecestrategy.addstrategy('return70', (price) => {
  return price + parseint(price / 100) * 70
})
console.log(pricecestrategy.strategyfunction('return70', 100))  // 170

还有我们的表单验证也可以使用策略模式

// 定义一个策略对象
let inputstrategy = function(){
  // 内部算法对象 
  let strategy = {
    notnull(value){
      return /\s+/.test(value) ? '请输入内容' : ''
    },
    number(value){
      return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '' : '请输入数字'
    }
  }
  // 策略方法调用接口
  return {
    check(type, value) {
      // 去除空白符
      value = value.replace(/^\s+|\s+$/g, '')
      return strategy[type] && strategy[type](value)
    },
    // 添加策略
    addstrategy(type, fn){
      strategy[type] = fn
    }
  }
}()

// 添加算法
inputstrategy.addstrategy('nickname', (value) => {
  return /^[a-za-z]\w{3,7}$/.test(value) ? '' : '请输入4-8为昵称'    
})

总结

策略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响 到客户端的情况下发生变化。通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。

策略模式中的三个对象:

  • 环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。
  • 抽象策略对象:它可由接口或抽象类来实现。
  • 具体策略对象:它封装了实现同不功能的不同算法。

利用策略模式构建应用程序,可以根据用户配置等内容,选择不同有算法来实现应用程序的功能。具体的选择有环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。

优点:
  1. 优化多重条件判断,采用策略模式是的算法更利于维护
  2. 可扩展性,策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  3. 策略类之间可以*切换,由于策略类都实现同一个接口,所以使它们之间可以*切换。
缺点:
  1. 由于选择哪种算法的决定权在用户,所以对用户来说就必须了解每种算法的实现。
  2. 由于每种算法间相互独立,这样对于一些复杂的算法处理相同逻辑的部分无法实现共享,这就会造成一些资源的浪费。