前面两章讲的都是常见的 创建型设计模式, 这章讲一个 行为型设计模式
定义
定义一系列的算法, 把它们封装起来, 并且使它们可以互相替换
意图
解决在很多相似场景下用过多 if else 所带来的复杂和难以维护问题
例子: 公司绩效考核与年终奖
class Kpi {
constructor(grade, base) { //1.等级 2.奖金基数
this.grade = grade
this.base = base
}
//奖金
bonus() {
if (this.grade === 'D') {
return '恭喜恭喜! 喜提 n+1'
}
if (this.grade === 'C') {
return this.base * 2 //双倍工资
}
if (this.grade === 'B') {
return this.base * 4 //4倍工资
}
if (this.grade === 'A') {
return this.base * 6 //6倍工资
}
}
}
这样公司财务计算每个人的年底奖金就非常方便了,
比如小王 评级B 底薪10000
const wang = new Kpi('B', 10000)
wang.bounds() // 40000
上面这个就是没用策略模式的写法, 功能没啥问题, 就是看着像裹脚布又臭又长, 每次新增都得往里面塞, 这个方法会越来越长。
这还只是一个简单例子, 要是判断键盘按键 那不得判断108键啊!!!!
接下来我们用策略模式改造下
class Kpi {
static grade
constructor(grade, base) { //1.等级 2.奖金基数
this.grade = grade
this.base = base
}
bonus() {
return {
A: this.isA,
B: this.isB,
C: this.isC,
D: this.isD,
} [this.grade]
},
isA() {
return this.base * 6
}
isB() {...}
isC() {...}
isD() {...}
}
感觉结构清晰多了, 后续如果有其它等级加进来也很方便, 不会把bonus 方法搞炸了。
类似的案例还有前端表单验证
class Rule {
//验证身份证
isCardNumber(value) {
const rel = /^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$/
return rel.test(value)
}
isMobile(value) {
...
}
// 如果想提供报错信息,可以这么写
async isEmpty(value, err) {
if( value.length< 1) {
alert(err)
return false
}
}
}
项目中我们可以根据需求往里面添加方法, 至于想要 链式调用
或者 同步
的写法都可以, 比如要同步那么就可以如下写法
//这里举个栗子
isEmpty(value) {
return new Promise((resolve, reject) => {
if(value.length < 1) {
reject('该选项不能为空')
}
resolve(true)
})
}
async function submit() {
const myRule = new Rule()
await myRule.isEmpty(this.name, '名字不能为空哦')
await myRule.isMobile(this.phone)
}
最后的轻语
永远不要放弃寻找第三选择
我们写代码也是, 时刻想着是否有更好的方案, 慢慢的就能写出可维护的代码了