• js 设计模式——策略模式


    策略模式(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. 由于每种算法间相互独立,这样对于一些复杂的算法处理相同逻辑的部分无法实现共享,这就会造成一些资源的浪费。
  • 相关阅读:
    Linux下的内核测试工具——perf使用简介
    浅谈C++中指针和引用的区别
    成为Java顶尖程序员 ,看这11本书就够了
    spring注解详解
    Spring AOP详解和实现方式
    Spring IoC中各个注解的理解和使用
    NameNode配置HA后及其反过程Hive路径不正确的问题解决
    [maven] 常用插件解析
    Saiku3.15去除License与主界面
    saiku系列文章
  • 原文地址:https://www.cnblogs.com/loveyt/p/11057884.html
Copyright © 2020-2023  润新知