Separar as partes que não mudam das partes que mudam é um tema de todo padrão de design
Qual é o padrão de estratégia?
O padrão de estratégia consiste em classificar e encapsular razoavelmente diferentes algoritmos separadamente, de modo que diferentes algoritmos possam ser substituídos entre si sem afetar os usuários dos algoritmos.
A seguir, usamos um exemplo simples para ilustrar o modo de estratégia:
por exemplo: Com base na pontuação recebida, determine se o status atual da pontuação é reprovado, aprovado ou excelente.
// 一般写法
const score1 = 59;
function judgeScore(score) {
if(score < 60 ) {
return '不及格'
}else if(score > 60 && score < 85) {
return '及格了'
}else if(score >= 85) {
return '优秀'
}
}
judgeScore(58); // 不及格
judgeScore(66); // 及格
judgeScore(88); // 优秀
Como mostrado acima:
Precisamos usar vários if...else... para julgar as pontuações recebidas. Se a pontuação for dividida de forma mais precisa, o código será muito redundante e difícil de manter.
A seguir, vamos dar uma olhada nos efeitos alcançados usando o padrão de estratégia:
// 策略模式
let strategies = {
noPass: function(score, tipText) {
if(score < 60) {
return tipText;
}
},
pass: function(score, tipText) {
if(score > 60 && score < 85) {
return tipText
}
},
excellent: function(score, tipText) {
if(score >= 85) {
return tipText;
}
}
}
function judgeScore(score) {
let noPass = strategies['noPass'](score, '不及格');
let pass = strategies['pass'](score, '及格');
let excellent = strategies['excellent'](score, '优秀');
let res = noPass || excellent || pass;
return res;
}
judgeScore(58); // 不及格
judgeScore(66); // 及格
judgeScore(88); // 优秀
A aplicação mais clássica do padrão de estratégia é na validação de formulários:
// 一般写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="xxxx" id="myForm">
<input type="text" placeholder="userName" name="userName" />
<input type="text" placeholder="password" name="password"/>
<button>登录</button>
</form>
<script>
const myForm = document.getElementById('myForm');
myForm.onsubmit = function () {
if(myForm.telephone.value === '') {
console.log('电话号码不能为空');
return false;
}else if(myForm.userName.password === '') {
console.log('密码不能为空');
return false;
}
}
</script>
</body>
</html>
Conforme mostrado no código acima:
O mesmo código é fácil de entender, mas toda vez que adicionamos um item de formulário, precisamos adicionar uma instrução if.
A seguir aplicamos o padrão de estratégia para transformá-lo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="xxxx" id="myForm">
<input type="text" placeholder="telephone" name="telephone" />
<input type="text" placeholder="至少8位数" name="password"/>
<button>登录</button>
</form>
<script>
const myForm = document.getElementById('myForm');
let strategies = {
isNotEmpty: function(value, tipText) {
if(vlaue === '') {
return tipText;
}
},
minLength: function(value, length, tipText) {
debugger
if(value.length < length) {
return tipText;
}
},
matchTelephone: function(value, tipText) {
if(!/^1[3|4|5|7|8|9][0-9]{9}$/.test(value)) {
return tipText;
}
}
}
class Validator {
constructor(strategies) {
this.strategies = strategies;
this.cache = [];
}
add(dom, rule, tipText) {
// add(dom, 'minLength:8', '***')
this.cache.push(function() {
const r = rule.split(':');
const strategy = r.shift();
const params = [...r, tipText];
return strategies[strategy](dom, ...params);
})
}
startValidate() {
for(let i = 0; i < this.cache.length; i++) {
let msg = this.cache[i]();
if(msg) {
return msg;
}
}
}
}
let validateFunc = function() {
let validator = new Validator();
validator.add(myForm.telephone.value, 'matchTelephone', '请输入正确的手机号格式');
validator.add(myForm.password.value, 'minLength:8', '密码至少8位数');
let tipText = validator.startValidate();
return tipText;
}
myForm.onsubmit = function(e) {
const tipText = validateFunc();
if(tipText) {
console.log(tipText);
return false // 有错误,阻止表单提交
}
}
</script>
</body>
</html>