什么是策略模式
在策略模式中定义了一系列算法,将每一个算法封装起来,并让他们可以互相替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为型模式。
策略模式的缺点:
- 策略模式利用组合、委托和多态等技术思想,可以有效的避免多种条件选择语句
- 策略模式提供了对开放封闭原则的完美支持,将算法封装在独立的
strategy
中,使得它易于切换,易于理解,易于拓展 - 策略模式中的算法也可以服用在系统的其他地方,从而避免许多重复的复制黏贴工作
- 在策略模式利用组合和委托来让Context拥有执行算法的能力,这也是i继承一种更轻便的替代方按
缺点:
- 编写难度加大,代码量变多,这是最直观的一个缺点,但也算不上缺点,毕竟不能以代码量多少衡量代码质量
- 首先,使用策略模式会在程序中增加许多策略类或者策略对象,但实际上这比把它们负责的逻辑堆砌在
Content
中要好 - 其次要使用策略模式,必须了解所有的
strategy
,必须了解各个strategy
之间的不同点,这样才能选择一个合适的strategy
。这是违反最少知识原则的
现在我们有一个表单校验需求,在提交按钮之前,有如下几条校验规则:
- 账号不能为空
- 密码长度最少7位
一开始我可能会这么写
<template> <div> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.account"></el-input> </el-form-item> <el-form-item label="密码"> <el-input type="textarea" v-model="form.passowrd"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">登录</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data(){ return { form: { account: '',passowrd: '' },} },methods:{ onSubmit(){ let {account,passowrd} = this.form; if(!account){ this.$message.error('请输入账号') }else if(passowrd.length<7){ this.$message.error('密码长度不能低于7位') }else{ this.$message.success('表单校验成功') } } } } </script>
这是一种很常见的编码方式,但它有很明显的缺点:
- 包含了很多if语句,这些语句要覆盖所有的校验规则。
- 若校验规则有变,需要改动
onSubmit
校验规则,违反开闭原则 - 算法复用性差
下面让我们使用策略模式重构表单校验
<template> <div> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.account"></el-input> </el-form-item> <el-form-item label="密码"> <el-input type="textarea" v-model="form.passowrd"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">登录</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data(){ return { form: { account: '',strategies:{ isNoEmpty(data,key){ return new Promise((resolve,reject)=>{ if(data[key]){ resolve() }else{ reject('请输入账号') } }) },minLength(data,reject)=>{ if(data[key].length<7){ reject('密码最低不能少于7个字') }else{ resolve() } }) } } } },methods:{ onSubmit(){ let {strategies} = this; strategies.isNoEmpty(this.form,'account') .then(()=>strategies.minLength(this.form,'passowrd')) .then(()=>{ this.$message.success('表单校验成功') }).catch(err=>{ this.$message.error(err) }) } } } </script>
让我们把上面代码优化下,实现简单的element
表单校验
<template> <div> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.account"></el-input> </el-form-item> <el-form-item label="密码"> <el-input type="textarea" v-model="form.passowrd"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">登录</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data(){ return { form: { account: '',rules:{ account:[ {methodName:"isNoEmpty",message:'请输入账号'} ],passowrd:[ {methodName:"isNoEmpty",message:'请输入密码'},{methodName:"minLength",length:7,message:'密码最低不能少于7位'} ],},strategies:{ minLength(val,err,length){ if(val.length<length){ return err; } },isNoEmpty(val,err){ if(!val){ return err; } } } } },methods:{ strategiesFun(data){ let {strategies,rules} = this; let err = [] for(let key in data) { rules[key].forEach(item=>{ let _err = strategies[item.methodName](data[key],item.message,item.length); _err && err.push(_err); }); } return new Promise((resolve,reject)=>{ err.length ? reject(err[0]) : resolve() }) },onSubmit(){ this.strategiesFun(this.form) .then(()=>{ this.$message.success('表单校验成功') }).catch(err=>{ this.$message.error(err) }) } } } </script>
比如,某天新增加一个需求,要求账号长度不小于5位数我们只需要在rules
对象中增加一条校验规则就行
rules:{ account:[ {methodName:"isNoEmpty",message:'请输入账号'},length:5,message:'账号最低不能少于5位'} ],passowrd:[ {methodName:"isNoEmpty",message:'密码最低不能少于7位'} ],
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。