策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换,就叫做策略模式。
策略模式与状态模式非常相似,都是为了避免大量堆砌条件语句,但在使用意图上却迥然不同:策略模式中的各个策略对象是没有任何关联的平行语句,使用者可以随心所欲选择某一种或某几种来达到不同的效果。
应用场景
比如我们现在需要编写一个表单校验的功能,以往的代码可能是下面这样:
例子:
价格:<input type="text" />
<script>
const Input = document.querySelector('input');
Input.addEventListener('focusout', (e) => {
if (Object.is(e.target.value, '')) {
console.log('不能为空!');
} else if (typeof e.target.value !== 'number') {
console.log('必须是数字!');
}
});
</script>
上面这种比较常见的代码编写方式有几个缺点,首先是堆砌了过多的条件语句,其次是扩展性与复用性很低。针对这些问题,我们使用策略模式重构代码:
例子:
价格:<input type="text" />
<script>
const CheckFrom = (() => {
// 校验规则
const strategies = {
isNotEmpty(value, errMsg) {
if (Object.is(value, '')) {
return errMsg;
}
},
isNumber(value, errMsg) {
for (let n of String(value))
if (!'0123456789'.includes(n)) {
return errMsg;
}
},
};
// 添加并启动校验规则的方法
const add = ({ element, rules = [] } = {}) => {
for (let item of rules) {
// 如果校验中有返回值,说明校验没有通过
const err = strategies[item.rule](element.value, item.errMsg);
if (err) {
console.log(err);
}
}
};
return {
add,
};
})();
// 测试策略模式函数
const Input = document.querySelector('input');
Input.addEventListener('focusout', (e) => {
CheckFrom.add({
element: e.target,
rules: [
{ rule: 'isNotEmpty', errMsg: '不能为空!' },
{ rule: 'isNumber', errMsg: '必须是数字!' },
],
});
});
</script>
使用策略模式重构后的代码,仅仅通过配置就可以完成一个表单的校验,而且这些校验规则可以复用到任何地方。
如有错误,欢迎指正,本人不胜感激。