策略模式
一个表单验证的例子
给一个html页面,带一个form表单
<form id='login-form' action="" method="post">
<label for="account">手机号</label>
<input type="number" id="account" name="account">
<label for="password">密码</label>
<input type="password" id="password" name="password">
<button id='login'>登录</button>
</form>
通常我们的做的简单表单验证
<script>
var loginForm = document.getElementById('login-form');
loginForm.onsubmit = function (e) {
e.preventDefault();
var account = document.getElementById("account").value;
var pwd = document.getElementById("password").value;
if(account===null||account===''){
alert('手机号不能为空');
return false;
}
if(pwd===null||pwd===''){
alert('密码不能为空');
return false;
}
if (!/(^1[3|4|5|7|8][0-9]{9}$)/.test(account)) {
alert('手机号格式错误');
return false;
}
if(pwd.length<6){
alert('密码不能小于六位');
return false;
}
// 发送请求
}
</script>
通常我们都是想,直接用if else来解决各种表单的验证,但是这样做的问题是,每次新加一个验证规则都要找到onsubmit函数,添加if判断,而且还要知道对应的字段名,麻烦就算了,最重要的是逻辑不能复用,如果有多个地方用到这个表单判断又要重写,这时候用到策略模式,一个策略就像一个诸葛亮的精囊妙计
策略模式简介
- 意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换
- 方式:创建一个策略对象和一个context,context的行为会随着不同的策略对象有不同的表现
- 解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
使用策略模式构建的表单校验
// 策略对象
const strategy = {
isNoEmpty: (val) => {
if(val === null || var == '') {
return '不能为空'
}
},
isPhoneNum: (val) => {
if (!/(^1[3|4|5|7|8][0-9]{9}$)/.test(account)) {
return '手机号格式错误'
}
},
length: (val, len) => {
if (val.length > len) {
return '不能小于六位'
}
}
}
// 上下文
const context = (formRule) => {
if(let i = 0; i < formRule.length; i++) {
const item = formRule[i]
const res = strategy[item.type](item.val)
if(res) res
}
}
/**
class validator {
constructor() {
this.strategy = null
this.formRule =null
}
// 设置策略对象
setStrategy(val) {
this.startegy = val
}
// 设置规则
setFormRule() {
this.formRule = val
}
// 验证,相对于context
validate() {
if(let i = 0; i < formRule.length; i++) {
const item = formRule[i]
const res = strategy[item.type](item.val)
if(res) res
}
}
}
*/
// 提交
function subimit() {
const form = [
{type: 'isNoEmpty', val:account },
{type: 'isNoEmpty', val:pwd },
{type: 'isPhoneNum', val:account },
{type: 'length', val:pwd },
] // 简化的表单数据
// 验证
if(!context(form)) return
/**
// 验证
const validator = new context()
validator.setStrategy(strategy)
validator.setFormrule(form)
if(!validator.validate()) return
*/
// 发起请求...
}
这里用的就是策略模式,定义了一个策略对象,和一个context控制执行,可以很方便的实现逻辑复用
史诗级的表单验证
相关库 async-validator,可以找相关源码了解,同样是用了了策略模式。
优缺点
优点:
- 把相互独立的代码块封装在一处,方便以后管理扩展
- 优于继承,继承的算法是封装在类里的,在算法多的情况下,会衍生很多不同的类,而类里面算法和使用者耦合也会增加维护难度
- 优化繁重的if else,提升代码简洁度
缺点:
- 选择算法时,必须了解全部算法的使用方法,才能选择合适的方法,违反最小知识原则
- 算法间相互独立,如果有共同部分无法实现共享
思考
- 在哪些场景下适用,哪些场景不适用?
- 跟状态模式有什么不一样?
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1249118795@qq.com