前言:要提升代码水平,就绕不开设计模式。之前也有过一些了解,但并没有深入学习。最近准备系统的学习一下设计模式,提高设计,解耦的能力,发现了一本好书《JavaScript设计模式与开发实践》,所以边读边写,把常用的设计模式学习并记录在这里。
单例模式的定义:定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换。
策略模式是最亲民的设计模式了,即使之前没学过,在很多代码中我们都会不知不觉的使用简单的策略模式,但本篇简述的完整策略模式更加的面向对象。
在JavaScript
中,函数也是对象,最直接的做法就是把策略直接定义为函数:
// 根据绩效和工资计算年终奖的例子:
// 根据绩效不同,有不同的算法,把这些算法封装成不同的策略
const strategies = {
S: function(salary) {
return salary * 4;
},
A: function(salary) {
return salary * 3;
},
B: function(salary) {
return salary * 2;
}
}
const calculateBouns = function(level, salary) {
return strategies[level](salary);
}
calculateBouns(S, 10000);
可以看到,上边的做法其实不需要学习,我们在日常编码中就很可能会自发的这样使用,仅仅针对这个例子而言,甚至可以更加简洁。当然这样做有好有坏,可以根据实际情况决定,如下:
const strategies = {
S: 4,
A: 3,
B: 2,
}
const calculateBouns = function(level, salary) {
return strategies[level] * salary;
}
calculateBouns(A, 20000);
我们有个很常见的表单校验需求,希望这些校验规则能够方便的替换和组合使用,来预防后期的需求变更。
// 表单结构
<html>
<body>
<form action='xxx' id='registerForm' method="POST">
请输入用户名:<input type='text' name='userName' />
请输入密码:<input type='text' name='password' />
请输入手机号:<input type='text' name='mobile' />
</form>
</body>
<html>
// js
/******* 策略对象 ********/
const strategies = {
isNotEmpty: function(val, errMsg) {
if(val === '') {
return errMsg
}
},
minLength: function(val, minLen, errMsg) {
if(val.length < minLen) {
return errMsg
}
},
isMobile: function(val, errMsg) {
if(!/(^1[3|5|8][0-9]{9}$)/.test(val)) {
return errMsg
}
}
}
/******* Validator 类 ********/
class Validator {
constructor() {
this.cache = [];
}
add(dom, rules) {
rules.forEach(rule => {
const strategyArr = rule.strategy.aplit(':');
const errMsg = rule.errMsg;
// catch中保存的是校验方法
this.catch.push(function() {
// 取出冒号左边的策略名称
// 如 minLen: 6,为最小长度为6位
const strategy = strategyArr.shift();
// 把实际的输入值从左侧插入参数数组
strategyArr.unshift(dom.value);
// 把错误提示从右侧插入参数数组
strategyArr.push(errMsg);
// 取得对应的策略,使用apply在dom下执行,传入参数数组strategyArr
return strategies[strategy].apply(dom, strategyArr);
})
})
}
start() {
this.cacht.forEach(validatorFunc => {
const errMsg = validatorFunc();
if (errMsg) {
return errMsg;
}
})
}
}
/******* 调用代码 ********/
const registerForm = document.getElementById('registerForm');
const validataFunc = function() {
const validator = new Validator();
// 校验对象增加校验规则
validator.add(registerForm.userName, [{
strategy: 'isNotEmpty',
errMsg: '用户名不能为空',
}, {
strategy: 'minLen: 10',
errMsg: '用户名长度不能小于10位',
}]);
validator.add(registerForm.password, [{
strategy: 'minLen: 6',
errMsg: '用户名长度不能小于6位',
}]);
validator.add(registerForm.mobile, [{
strategy: 'isMobile',
errMsg: '手机号码格式不正确',
}]);
// 校验对象开始校验
const errMsg = validator.start();
return errMsg;
}
registerForm.onsubmit = function() {
const errMsg = validataFunc();
if(errMsg) {
alert(errMsg);
return
}
// do submit
}