JavaScript 设计模式之策略模式

策略模式

结构上看,它与状态模式很像,也是在内部封装一个对象,然后通过返回的接口对象实现对内部对象的调用,不同点是,策略模式不需要管理状态、状态间没有依赖关系、策略之间可以相互替换、在策略对象内部保存的是相互独立的一些算法。

创建策略

javascript 复制代码
const Price = function () {
  const strategy = {
    return30: function (price) {
      return price * 0.3
    },
    return50: function (price) {
      return price * 0.5
    },
    return80: function (price) {
      return price * 0.8
    },
  }
  return function (algorithm, price) {
    return strategy[algorithm] && strategy[algorithm](price)
  }
}
const getPrice = Price()
console.log(getPrice('return30', 100)) // 30
console.log(getPrice('return50', 100)) // 50
console.log(getPrice('return80', 100)) // 80

表单校验

比如我们可以有一个简单的表单校验

javascript 复制代码
const ValidatorFactory = (function () {
  const Strategy = {
    isNonEmpty: function (value, errorMsg) {
      return value === '' ? errorMsg : undefined
    },
    minLength: function (value, errorMsg, {length}) {
      return value.length < length ? errorMsg : undefined
    },
    isMobile: function (value, errorMsg) {
      return !/^1[3|5|7|8]\d{9}$/.test(value) ? errorMsg : undefined
    },
    isEmail: function (value, errorMsg) {
      return !/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+/.test(value) ? errorMsg : undefined
    },
    // ...
  }
  return {
    check:function (values,rules) {
      for (let i in rules) {
        const rule = rules[i]
        const errorMsg = rule.errorMsg
        const strategy = Strategy[rule.strategy]
        const value = values[rule.value]
        if (value === undefined) {
          continue;
        }
        if (!strategy) {
          throw new Error('没有这个策略')
        }
        // 执行策略
        const result = strategy(value, errorMsg, rule)
        if (result) {
          return result
        }
      }
      return true
    },
    addStrategy: function (value, fn) {
      Strategy[value] = fn
    }
  }
}())
const rules = [
  {
    strategy: 'isNonEmpty',
    value: 'username',
    errorMsg: '用户名不能为空',
  },
  {
    strategy: 'minLength',
    value: 'username',
    length: 6,
    errorMsg: '用户名长度不能小于6位',
  },
  {
    strategy: 'isMobile',
    value: 'phoneNumber',
    errorMsg: '手机号码格式不正确',
  },
  {
    strategy: 'isEmail',
    value: 'emailAddress',
    errorMsg: '邮箱地址格式不正确',
  },
  // ...
]
const values1 = {
  username: '',
}
const validator1 = ValidatorFactory.check(values1, rules) // 用户名不能为空

const values2 = {
  username: '22',
}
const validator2 = ValidatorFactory.check(values2, rules) // 用户名长度不能小于6位

ValidatorFactory.addStrategy('password', function (value, errorMsg) {
  return value === '' ? errorMsg : undefined
})
const values3 = {
  username: '2221212',
  phoneNumber: '13322221111',
  password:''
}
rules.push({
  strategy: 'password',
  value: 'password',
  errorMsg: '密码不能为空',
})
const validator3 = ValidatorFactory.check(values3, rules) // 密码不能为空

总结

策略模式最主要的特色是创建一系列策略算法,每组算法处理的业务都是相同的,只是处理的过程或者处理的结果不一样,它们又是可以相互替换的,这样就解决了算法与使用者组算法相互之间的独立性,该模式更方便于对每组算法之间的耦合。第一,策略模式封装了一组代码簇,并且封装的代对于策略模式的优点可以归纳为码相互之间独立,便于对算法的重复用,提高了算法的复用率。第二,策略模式与继承相比,在类的继承中继承的方法是被封装在类中,因此当需求很多算法时,就不得不创建出多种类,这样会导致算法与算法的使用者耦合在一起,不利于算法的独立演化,并且在类的外部改变类的算法难度也是极大的。第三,同状态模式一样,策略模式也是一种优化分支判断语句的模式更有利于维护。

相关推荐
YA33319 小时前
java设计模式六、装饰器模式
java·设计模式·装饰器模式
半夏知半秋1 天前
游戏登录方案中常见的设计模式整理
服务器·开发语言·笔记·学习·游戏·设计模式·lua
Asort1 天前
JavaScript设计模式(十八)——备忘录模式:状态保存与恢复的艺术
前端·javascript·设计模式
原来是好奇心1 天前
告别if-else!使用策略模式优雅处理多种MQTT消息类型
java·mqtt·设计模式·策略模式·emqx
AY呀1 天前
# 从 HTML5 敲击乐到前端工程化:模块化开发如何重塑交互体验
设计模式
天南星1 天前
23种设计模式-深度讲解-7. 装饰器模式 (Decorator)
后端·设计模式
hans汉斯1 天前
【计算机科学与应用】基于多光谱成像与边缘计算的物流安全风险预警模式及系统实现
大数据·数据库·人工智能·设计模式·机器人·边缘计算·论文笔记
杯莫停丶1 天前
设计模式之:适配器模式
设计模式·适配器模式
xiezhr1 天前
见过哪些醍醐灌顶的Java代码:从"卧槽"到"原来如此"的顿悟
java·后端·设计模式
WaWaJie_Ngen1 天前
【设计模式】适配器模式(Adapter)
设计模式·适配器模式