【设计模式】使用策略模式优化表单校验逻辑

什么是策略?

所谓策略,就是根据已知条件决定要做出怎样的行为。

举个栗子:我要实现一个表单校验功能,要求 name 不能为空且长度必须大于 2 且小于 4,age 不能为空且必须为纯数字。

这样的判断逻辑直接用 if-else 就可以实现:

js 复制代码
function valid() {
  // 表单校验逻辑
  if (!form.name) {
    alert("name 不能为空");
    return false;
  }

  if (form.name.length < 2) {
    alert("name 长度必须大于 2 ");
    return false;
  }

  if (form.name.length > 4) {
    alert("name 长度必须小于 4");
    return false;
  }

  if (!form.age) {
    alert("age 不能为空");
    return false;
  }

  if (!/^\d+$/.test(form.age)) {
    alert("age 只能为数字");
    return false;
  }

  return true;
}

这种实现方式有几个缺点:

  • 最终实现的 valid() 函数比较庞大,并且包含了很多 if-else 语句,需要在这里覆盖所有的校验规则。
  • 算法复用性差,如果其他地方也要进行类似的校验,就需要将这些校验逻辑到处复制粘贴。

策略模式就是为了解决这些问题而生的。

什么是策略模式?

策略模式的核心思想是将算法与使用对象分开,对象不是直接实现单个算法,而是在执行时决定要使用哪些算法。

它基于组合优于继承的原则,通过对一系列算法的封装,使它们在运行时可以互换。

这使得对象更加灵活和可重用,因为可以轻松添加或修改不同的策略,而无需更改对象的核心代码。

以上面的表单校验逻辑为例,这段代码中有四个策略: 字段不能为空字段长度必须大于x字段长度必须小于x字段只能为数字

用策略模式优化表单校验逻辑

优化思路:

  1. 隔离校验逻辑。
  2. 封装校验类,统一管理校验逻辑。

Validator 类中封装所有校验策略,并提供通用的使用接口。

js 复制代码
class Validator {
  /**
   * 内置校验策略
   */
  static strategy = {
    require(value, errorMsg) {
      if (value === "" || value === undefined || value === null) {
        return errorMsg;
      }
    },
    minLength(value, errorMsg, length) {
      if (value.length < length) {
        return errorMsg;
      }
    },
    maxLength(value, errorMsg, length) {
      if (value.length > length) {
        return errorMsg;
      }
    },
    number(value, errorMsg) {
      if (!/^\d+$/.test(value)) {
        return errorMsg;
      }
    },
  };

  rules = [];

  /**
   * 添加一条校验规则
   * @param {*} value 待校验的值
   * @param {*} validFn 校验方法
   * @param {*} errorMsg 错误信息
   */
  add(value, validFn, errorMsg, ...args) {
    if (typeof validFn === "function") {
      this.rules.push(validFn.bind(this, value, errorMsg, ...args));
    } else {
      console.error("validFn 必须是一个函数");
    }
  }

  /**
   * 启动校验
   */
  valid() {
    let length = this.rules.length;
    while (length--) {
      const rule = this.rules.shift();
      const errorMsg = rule();
      if (errorMsg) {
        return errorMsg;
      }
    }
  }
}

业务逻辑中的使用方式如下:

js 复制代码
// 校验逻辑,返回值为错误信息,无返回值表示校验通过
function valid() {
  const validator = new Validator();
  // 给 name 设置校验规则
  validator.add(form.name, Validator.strategy.require, "name 不能为空");
  validator.add(
    form.name,
    Validator.strategy.minLength,
    "name 长度必须大于 2",
    2
  );
  validator.add(
    form.name,
    Validator.strategy.maxLength,
    "name 长度必须小于 4",
    4
  );

  validator.add(form.age, Validator.strategy.require, "age 不能为空");
  validator.add(form.age, Validator.strategy.number, "age 只能为数字");

  // 校验
  return validator.valid();
}

使用策略模式重构表单校验逻辑后,可以通过配置的方式就完成一个表单的校验,这些校验规则也可以更方便的复用。

总结

策略模式的优点是提高代码的灵活性和可复用性。

它的缺点是使用者必须了解所有的策略,才能选择合适的策略。

如果逻辑比较简单,使用 if-else 足以应对,就没必要用策略模式。

参考

《JavaScript 设计模式与开发实践》

Strategy pattern

A Beginner's Guide to the Strategy Design Pattern

Strategy

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax