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


    1. 通过if来新增分支
    let bonus = function(performance, salary) {
      if (performance === 'S') {
        return salary * 4
      }
      if (performance === 'A') {
        return salary * 3
      }
      if (performance === 'B') {
        return salary * 2
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 通过扩展函数来新增分支.
    let performanceS = function() {}
    performanceS.prototype.calculate = function(salary) {
      return salary * 4
    }
    let performanceA = function() {}
    performanceA.prototype.calculate = function(salary) {
      return salary * 3
    }
    let performanceB = function() {}
    performanceB.prototype.calculate = function(salary) {
      return salary * 2
    }
    let performanceC = function() {}
    performanceC.prototype.calculate = function(salary) {
      return salary * 1
    }
    
    let Bonus = function() {
      this.salary = null
      this.strategy = null
    }
    Bonus.prototype.setSalary = function(salary) {
      this.salary = salary
    }
    Bonus.prototype.setStrategy = function(strategy) {
      this.strategy = strategy
    }
    Bonus.prototype.getBonus = function(){
      if(!this.strategy) {
        throw new Error('未设置绩效')
      }
      return this.strategy.calculate(this.salary)
    }
    let bonus = new Bonus()
    bonus.setSalary(10000)
    bonus.setStrategy(new performanceS()) // 问题在于无法动态传入标志S.
    console.log(bonus.getBonus())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    1. 通过对下下标来新增分支
    let strategy = {
      'S': function(salary) {
        return salary * 4
      },
      'A': function(salary) {
        return salary * 3
      },
      'B': function(salary) {
        return salary * 2
      },
    }
    let calculateBonus = function(level, salary) {
      return strategy[level](salary)
    }
    console.log(calculateBonus('A', 20000))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 使用new Map()
      最近比较多使用new Map([[fn1, cb1], [fn2, cb2])的形式来实现策略模式,用来很爽。
      if的实现使用一句话替代,效果是自动查找并执行。
      格式如下:
    let s = new Map([
      [v => v > 1, cb2 => 1],
      [v => v > 2, cb2 => 2],
      ...
      [v => true, cb2 => 1000], // 默认值
    ])
    s.find(([f,cb])=>f() && cb).pop()()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 表单验证,一个及多个规则实现
    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Documenttitle>
    head>
    <body>
      <form action="/">
        <input type="text" name="account" value=""> 用户名
        <input type="text" name="pwd" value=""> 密码
        <input type="submit" value="提交" />
      form>
      <script>
        let strategies = {
          isNonEmpty(value, errorMsg) {
            if(value === '') {
              return errorMsg
            }
          },
          minLength(value, errorMsg, {length}){
            if(value.length < length) {
              return errorMsg
            }
          }
        }
        let dom = document.forms[0].account
        let validateFunc = function(){
          let validator = new Validator()
          validator.add(dom, [
            {validator: 'isNonEmpty', msg: '用户名不能为空'},
            {validator: 'minLength', length: 5, msg: '长度不能为空'},
          ])
          let errorMsg = validator.start()
          return errorMsg
        }
        let Validator = function(){
          this.cache = []
        }
        const isObject = v => Object.prototype.toString.call(v) === '[object Object]'
        Validator.prototype.add = function(dom, rules) {
          if(isObject(rules)) rules = [rules]
          rules.map(item => {
            let {validator:strategy, msg, ...rest} = item
            let cache = function(){
              let ary = []
              ary.unshift(dom.value) // 添加值
              ary.push(msg) // 值对应的错误信息
              ary.push(rest) // 其他信息,比如长度
              return strategies[strategy].apply(dom, ary)
            }
            this.cache.push(cache)
          })
        }
        Validator.prototype.start = function() {
          for(let i = 0, validateFunc; validateFunc = this.cache[i++];) {
            let msg = validateFunc()
            if(msg) {
              return msg
            }
          }
        }
        document.forms[0].addEventListener('submit', e => {
          let errorMsg = validateFunc()
          if(errorMsg) {
            console.log(errorMsg)
            e.preventDefault()
          }
        })
      script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
  • 相关阅读:
    OpenGL 的学习之路-4(变换)
    Linux系统换源
    区,段,碎片区与表空间结构
    通俗易懂!一文看懂手机Root的操作与防护
    FIR 中级应用 - AM 调幅波调制解调(FIR + FIFO)
    Go 字符串操作实战
    盘点66个Pandas函数,轻松实现“数据清洗”
    SpringBoot的starter到底是什么?
    Java面向对象编程
    腾讯云轻量2核4G5M可容纳多少人访问?
  • 原文地址:https://blog.csdn.net/junjiahuang/article/details/126462882