策略模式的核心思想是将算法的实现与使用分离开来。在策略模式中,算法被封装成独立的策略类,而使用这些策略的类则通过组合关系来使用这些策略。这使得算法可以独立于其使用者而变化,从而提高了代码的灵活性和可维护性。
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", "密码必须包含字母、数字、特殊字符");