Skip to content

Latest commit

 

History

History
executable file
·
103 lines (80 loc) · 3.43 KB

策略模式.md

File metadata and controls

executable file
·
103 lines (80 loc) · 3.43 KB

策略模式

策略模式的核心思想是将算法的实现与使用分离开来。在策略模式中,算法被封装成独立的策略类,而使用这些策略的类则通过组合关系来使用这些策略。这使得算法可以独立于其使用者而变化,从而提高了代码的灵活性和可维护性。

策略模式与表单校验

代码实现

const { curry, isFunction } = _;
function formValidator(strategies = {}) {
  const validators = [];

  function getVaildator() {
    // 函数柯里化
    return curry(async function (vaildator, errMessage, value) {
      const pass = await vaildator(value);
      if (!pass) {
        return errMessage;
      } else {
        return null;
      }
    });
  }

  function add(check, errMessage) {
    let checkFun = null;

    if (!check || (!isFunction(check) && !strategies[check])) {
      console.error(
        `不存在名为 ${check} 的校验项,请检查函数formValidator的参数`
      );
      return false;
    }

    checkFun = isFunction(check) ? check : strategies[check];

    validators.push(getVaildator()(checkFun, errMessage || ""));
  }

  async function check(value) {
    for (let i = 0; i < validators.length; i++) {
      const validator = validators[i];
      const error = await validator(value);
      if (error) return error;
    }
    return null;
  }

  return {
    add,
    check,
  };
}

使用

// 自定义校验策略---邮箱
const emailFormatReg = /^[\w\.-]+@[\w\.-]+(\.[\w\.-]+)+$/;
const emailSpecialSymbolReg = /^[[email protected]]+$/;
const emailFormStrategies = {
  checkEmpty: (value) => !!value,
  checkFormat: (value) => emailFormatReg.test(value),
  checkHasSpecialSymbol: (value) => emailSpecialSymbolReg.test(value),
};
// 自定义校验策略---密码
const pwdFormatReg =
  /^((?![(~!@#\$%^&\\*()\+\-=,\./;|<>\?)]+$)(?![\d]+$)(?![a-zA-Z]+$)[\d(~!@#\$%^&\\*()\+\-=,\./;|<>\?)a-zA-Z]+)$/;

const pwdSpecialSymbolReg = /^[a-zA-Z\d(~!@#\$%^&\\*()\+\-=,\./;|<>\?)]+$/;

const passwordStrategies = {
  checkEmpty: (value) => !!value,
  checkNotEqual: (equalValue, value) => value !== equalValue,
  checkEqual: (equalValue, value) => equalValue === value,
  checkLength: (value) => value.length >= 8 && value.length <= 16,
  checkFormat: (value) => pwdFormatReg.test(value),
  checkHasSpecialSymbol: (value) => pwdSpecialSymbolReg.test(value),
};

// -------------- 实例化并使用 --------------

const emailValidator = formValidator(emailFormStrategies);

emailValidator.add("checkEmpty", "邮箱不能为空");
emailValidator.add("checkFormat", "邮箱格式不正确");
emailValidator.add("checkHasSpecialSymbol", "邮箱不能包含特殊字符");

const passwordValidator = formValidator(passwordStrategies);

passwordValidator.add("checkEmpty", "密码不能为空");
passwordValidator.add("checkNotEqual", "密码不能和邮箱相同", "email");
passwordValidator.add("checkLength", "密码长度必须为8-16位");
passwordValidator.add("checkFormat", "密码必须包含字母、数字、特殊字符");

效果

完整的 demo 请看 👉 在线效果预览, 查看示例代码请点击此处