策略模式重构表单校验初探

1,143 阅读3分钟

什么是策略模式?

“策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。”

为什么要用策略模式重构?

  1. 代码里表单校验重复的校验代码块太多
  2. 之前没用过策略模式

策略模式的优缺点

优点:

  • 策略模式利用组合、委托和多态等技术思想,可以有效的避免多种条件选择语句
  • 策略模式提供了对开放封闭原则的完美支持,将算法封装在独立的strategy中,使得它易于切换,易于理解,易于拓展
  • 策略模式中的算法也可以服用在系统的其他地方,从而避免许多重复的复制黏贴工作
  • 在策略模式利用组合和委托来让Context拥有执行算法的能力,这也是i继承一种更轻便的替代方按

缺点:

  • 编写难度加大,代码量变多,这是最直观的一个缺点,但也算不上缺点,毕竟不能以代码量多少衡量代码质量
  • 首先,使用策略模式会在程序中增加许多策略类或者策略对象,但实际上这比把它们负责的逻辑堆砌在Content中要好
  • 其次要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy。这是违反最少知识原则的

结构图

0bb5880daafa7e08be9d6e99655d9cd2.png

具体步骤,(直接上代码)

1、首先建立一个文件strategie,定义好需要校验的规则

const strategies = {
  // 非空校验
  isNoneEmpty([val, errorMsg = '不能为空']) {
    if (!val && val !== 0) return errorMsg
  },
  // 手机号校验
  isMobile([val, errorMsg = '请输入正确的手机号码']) {
    const reg = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/
    if (!reg.test(val)) {
      return errorMsg
    }
  },
}

2、创建一个校验class

class Validator {
  cache: string[] = []
  constructor() {
    // 保存校验规则
    this.cache = []
  }

![0bb5880daafa7e08be9d6e99655d9cd2.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8f5a12db19f740a096a978274fb49c37~tplv-k3u1fbpfcp-watermark.image?)
  // 增加规则
  add({ values, rules }) {
    rules.forEach((rule) => {
      const { strategy, errorMsg } = rule
      const [strategyName] = strategy.split(':') // 接受length  maxLength:6
      this.cache.push(strategies[strategyName]([values, errorMsg]))
    })
  }

  check() {
    let msgArr = []
    this.cache.some((v) => {
      if (v) {
        msgArr.push(v)
      }
    })
    console.log(msgArr, 'msg')
    return msgArr[0]
  }
}

export default Validator

3、在该校验的地方引用

    const validator = new Validator()
    const rules = {
      chargeType: [
        {
          strategy: 'isNoneEmpty',
          errorMsg: '请选择要咨询服务',
        },
      ],
      cityId: [
        {
          strategy: 'isNoneEmpty',
          errorMsg: '请选择城市',
        },
      ],
      phone: [
        {
          strategy: 'isNoneEmpty',
          errorMsg: '手机号码不能为空',
        },
        {
          strategy: 'isMobile',
          errorMsg: '请输入正确的手机号码',
        },
      ],
    }
    this.formList.map((v) => {
      validator.add({
        values: this.submitData[v.prop],  // 你提交的字段
        rules: rules[v.prop],   // 校验的字段
      })
    })
    let errorMsg = validator.check()
    if (errorMsg) {
      uni.showToast({
        title: errorMsg,
        icon: 'none',
      })
      return false
    } else {
      return true
    }    

这样的话就可以了,以后如果要加校验的话,只需要在strategie里维护校验规则,然后在rule这增加引用就可以了,这样看上去和elementUI的校验有点类似,其实像大的UI框架的表单校验都是用策略模式维护,只不过他们写的要详细的多

结论

第一次写,参考了一下网上的例子结合了一下自身业务,时间不够所以考虑的不是很全面,写得不是很好,待优化点还挺多,还可以抽离一些公共点,后面再慢慢完善...