JavaScript策略模式详解:从年终奖计算到表单校验
本文深入解析JavaScript中的策略模式,通过年终奖计算和表单校验两个实际案例,展示如何利用策略对象替代复杂的if-else分支判断。文章详细说明了策略模式的定义、优缺点及代码实现,帮助开发者提升代码的可扩展性与可维护性,实现算法与使用场景的解耦。
概述
策略模式属于JavaScript设计模式中的行为型模式。
定义:
该模式定义了一系列算法,并将每个算法封装为独立的策略类或方法。它将系统中不变的部分与变化的部分分离,使得这些算法可以相互替换。
白话解释:
策略模式的核心在于根据不同的策略执行不同的方法,这看似与if-else分支判断类似,但其主要目的是解决多重条件判断带来的代码冗余和维护困难问题。
代码实现
需求:
年终将至,某公司决定提前发放年终奖,但计算规则与绩效考核紧密相关。具体方案如下:
绩效考核等级为S的员工,年终奖为个人月工资的4倍;
绩效考核等级为A的员工,年终奖为个人月工资的3倍;
绩效考核等级为B的员工,年终奖为个人月工资的2倍;
面对上述需求,常见的初始实现方式通常如下:
function calculateBonus(level,salary){
if(level === 'S'){
return salary*4;
}
if(level === 'A'){
return salary*3
}
if(level === 'B'){
return salary*2
}
}
console.log(calculateBonus("S",14000)); //56000
console.log(calculateBonus("A",10000)); //30000
console.log(calculateBonus("B",5000)); //10000
上述代码虽能解决当前需求,但从程序设计角度看存在优化空间。该方法逻辑庞大且包含大量分支判断,缺乏弹性。若未来增加C方案,需修改原有方法并添加新分支,这违反了开放封闭原则。
优化:
var strategies = {
"S":function(salary){
return salary*4
},
"A":function(salary){
return salary*3;
},
"B":function(salary){
return salary*2
}
}
var calculateBonus =function(level,salary){
return strategies[level](salary);
}
console.log(calculateBonus("S",14000)); //56000
console.log(calculateBonus("A",10000)); //30000
console.log(calculateBonus("B",5000)); //10000
通过引入策略模式对上述代码进行重构,我们定义了一个策略对象。calculateBonus函数根据传入的等级和工资,通过策略对象计算年终奖。重构后,代码结构更加简洁清晰。
在Web开发中,登录或注册页面的表单提交前通常需要进行数据校验。若不符合规则则禁止提交。在未学习设计模式前,此类校验往往也采用多重if-else判断。现在,我们使用策略模式来实现表单校验:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http:// xxx.com/register" id="registerForm" method="post">
请输入用户名:<input type="text" name="userName"/ >
请输入密码:<input type="text" name="password"/ >
请输入手机号码:<input type="text" name="phoneNumber"/ >
<button>提交</button>
</form>
</body>
<script>
// 定义策略类算法校验规则
var strategies = {
isNonEmpty: function( value, errorMsg ){
if ( value === '' ){
return errorMsg;
}
},
minLength: function( value, length, errorMsg ){
if ( value.length < length ){
return errorMsg;
}
},
isMobile: function( value, errorMsg ){
if ( !/(^1[3|5|8][0-9]{9}$)/.test( value ) ){
return errorMsg;
}
}
};
//Validator 类
var Validator = function(){
// 保存校验规则
this.cache = [];
};
//添加校验规则的方法
Validator.prototype.add = function( dom, rules ){
var self = this;
for ( var i = 0, rule; rule = rules[ i++ ]; ){
(function( rule ){
//将校验规则对象中的strategy属性的值进行分割
var strategyAry = rule.strategy.split( ':' );
var errorMsg = rule.errorMsg;
self.cache.push(function(){
//将校验规则对象中的strategy属性的第一个值返回回来装进strategy中
var strategy = strategyAry.shift();
//组成参数
strategyAry.unshift( dom.value );
//组装参数
strategyAry.push( errorMsg );
//找到策略对象执行方法装进cache变量中
return strategies[ strategy ].apply( dom, strategyAry );
});
console.log(strategyAry);
})( rule )
}
};
//开始校验方法
Validator.prototype.start = function(){
for ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){
//循环cache执行方法校验
var errorMsg = validatorFunc();
//如果执行策略对象方法中返回了errorMsg,就说明方法已经报错(没有通过校验规则)
if ( errorMsg ){
return errorMsg;
}
}
};
//调用校验
var registerForm = document.getElementById( 'registerForm' );
//定义方法可以自定义添加校验规则
var validataFunc = function(){
//实例化对象
var validator = new Validator();
//自定义添加校验规则
validator.add( registerForm.userName, [{
strategy: 'isNonEmpty',
errorMsg: '用户名不能为空'
}, {
strategy: 'minLength:6',
errorMsg: '用户名长度不能小于10 位'
}]);
validator.add( registerForm.password, [{
strategy: 'minLength:6',
errorMsg: '密码长度不能小于6 位'
}]);
//调用方法循环执行校验
var errorMsg = validator.start();
return errorMsg;
}
//点击提交按钮(提交事件)
registerForm.onsubmit = function(){
//执行上面自定义的校验方法
var errorMsg = validataFunc();
//如果errorMsg存在,即代表校验没有通过
if ( errorMsg ){
alert ( errorMsg );
return false;
}
};
</script>
</html>
通过策略模式,可以有效解决表单校验中大规模重复的if-else判断问题。上述代码注释已提供详细说明,学习设计模式需深入理解代码背后的思路。策略模式的主要思想是定义一系列算法,传入参数后,根据参数执行对应的算法规则。
总结
优点:
1、利用组合、委托和多态等技术与思想,可以避免使用多重条件选择语句;
2、将算法封装在独立的策略类中,使得算法易于切换、理解和扩展;
3、策略模式可在系统其他部分复用,从而避免重复的复制粘贴工作;
缺点:
1、程序中会增加许多策略类或策略对象;
2、使用策略类前必须清楚所有策略类的算法,否则难以做出正确的选择。
以上即为JavaScript策略模式的详细内容,更多关于JavaScript策略模式的资料请关注本站其它相关文章!
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09
