JavaScript策略模式详解:从年终奖计算到表单校验

作者:函数茶馆

时间:2026-10-24

浏览:476

本文深入解析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策略模式的资料请关注本站其它相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章