前端策略模式使用

文章讲述了如何通过策略模式重构表单验证函数,避免冗长的if-else语句,使代码更具弹性。通过定义策略对象和Validator类,实现校验规则的灵活添加和复用,提升代码可维护性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  // 验证创建Notice的信息
  const validate = () => {
    // 检测数据合法性
    if (!modalConfig.content) {
      message.error('重要提示不为空');
      return false;
	} 
	
	if (modalConfig.point > 100) {
        message.error('仙岩币不能超过100');
        return false;
	}

  	if (!/^1(3|5|7|8|9)[0-9]{9}$/.test(modalConfig.phone)) {
    message.error('手机号码格式不正确!');
    return false;
  	}

 	if (
    !/^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(modal	Config.email)
  ) {
    message.error('邮箱地址格式不正确!');
    return false;
  }
  if(){}
  if(){}
   ...
    return true;
  };

1、问题

这样编写代码,的确能够完成业务的需求,能够完成表单的验证,但是存在很多问题,比如:

  1. validate绑定的函数比较庞大,包含了很多的if-else语句,看着都恶心,这些语句需要覆盖所有的校验规则。
  2. validate绑定的函数缺乏弹性,如果增加了一种新的校验规则,或者想要把仙岩币数量校验从6改成8,我们都必须深入validate绑定的函数的内部实现,这是违反了开放-封闭原则的。
  3. 如果程序中增加了另一个表单,这个表单也需要进行一些类似的校验,那我们很可能将这些校验逻辑复制得漫天遍野。

2、用策略模式重构表单校验

  1. 期望使用:
const validate = () => {
    let validator = new Validator()

    validator.add(modalConfig.phone, [{
        strategy: 'isNonEmpty',
        errorMsg: '手机号码不能为空!'
    }, {
      strategy: 'minLength:11',
      errorMsg: '测试手机号码长度最小不为11!',
    },{
        strategy: 'isMoblie',
        errorMsg: '手机号码格式不正确!'
    }])

    validator.add(modalConfig.email, [{
        strategy: 'isNonEmpty',
        errorMsg: '邮箱地址不能为空!'
    }, {
        strategy: 'isEmail',
        errorMsg: '邮箱地址格式不正确!'
    }])
    let errorMsg = validator.start()
    return errorMsg
}
  1. 实现:
/*策略对象*/
const strategies = {
  isNonEmpty(value, errorMsg) {
    return value === '' ? errorMsg : void 0;
  },
  minLength(value, length, errorMsg) {
    return value.length < length ? errorMsg : void 0;
  },
  isMoblie(value, errorMsg) {
    const regPhone =
      /^((13[0-9])|(14[4,5-9])|(15[0-3,5-9])|(16[2,5-7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\d{8}$/;
    return !regPhone.test(value) ? errorMsg : void 0;
  },
  isEmail(value, errorMsg) {
    const regEmail = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
    return !regEmail.test(value) ? errorMsg : void 0;
  },
};

 /*Validator类*/
class Validator {
  constructor() {
    this.cache = []; //保存校验规则
  }
  add(value, rules) {
    for (let rule of rules) {
      let strategyAry = rule.strategy.split(':'); //例如['minLength',6]
      let errorMsg = rule.errorMsg; //'用户名不能为空'
      this.cache.push(() => {
        let strategy = strategyAry.shift(); //用户挑选的strategy
        strategyAry.unshift(value); //把input的value添加进参数列表
        strategyAry.push(errorMsg); //把errorMsg添加进参数列表,[dom.value,6,errorMsg]
        return strategies[strategy].apply(value, strategyAry);
      });
    }
  }
  start() {
    for (let validatorFunc of this.cache) {
      let errorMsg = validatorFunc(); //开始校验,并取得校验后的返回信息
      if (errorMsg) {
        //r如果有确切返回值,说明校验没有通过
        return errorMsg;
      }
    }
  }
}

3、项目中使用

使用antd组件表单填写 rule规则
如:

  const rule = {
    name: {
      type: 'string',
      required: true,
      message: '请输入名字'
    },
    age: [
      {
        type: 'number',
        message: '请输入number',
      },
      {
        message: '年龄必须大于 18',
        validator: (rule, value) => value > 18,
      },
    ]};

antd会帮助我们校验 name 是否是 string、age 是否是 number。而 antd其实是用的一个开源的 async-validator 校验库。

4、总结

当出现很多 if else 或者 switch 的时候,我们就可以考虑是否能使用策略模式了。
通过策略模式,我们可以把策略从业务代码中抽离出来,未来扩展的话无需深入到业务代码修改,只需要新增需要的策略,不会使得业务代码变得越来越臃肿。
甚至策略模式也可以更好的进行复用,如果其他业务场景需要类似的策略,直接引入即可,和原有的业务相互独立。

5、规范

复杂表单验证一律走策略模式。

小程序:表单部分较少且已有表单复杂度低,不做限制。

后台:
使用规范 (简单说明,详细可见群治分后台创建活动模块)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值