前端面试——设计模式之策略模式

策略模式

定义:定义一系列的算法,把它们一个个封装起来,并且使它们之间可以相互替换

将不变的部分和变化的部分分隔开是每个设计模式的主题,策略模式的目的就是将使用的算法和算法的实现分离开来

使用策略模式计算奖金
  • 绩效为S的人奖金为4倍工资,A为3倍,B为2倍,要求提供一段代码,方便地计算每个员工的奖金

  • //策略对象
    const strategies={
        'S':function(salary){
            return salary*4;
        },
        'A':function(salary){
            return salary*3;
        },
        'B':function(salary){
            return salary*2;
        }
    }
    
    //环境类
    const calculateBonus=function(level,salary){
        return strategies[level](salary);
    }
    
    console.log(calculateBonus('S',1000));//4000
    console.log(calculateBonus('A',1000));//3000
    
表单验证(多种校验规则)
  • 添加多种校验,如:既能校验它是否为空,又能校验输入文本长度

策略对象

  • const strategies={
        //验证表单是否为空
        isNonEmpty:function(value,errMsg){
            console.log(value,errMsg);
            if(value=='') return errMsg;
        },
        //验证文本长度
        minLength:function(value,length,errMsg){
            if(value.length<length) return errMsg;
        },
        //验证手机号格式
        isMobile:function(value,errMsg){
            if(!/^1[3|5|8][0-9]{9}$/.test(value)) return errMsg;
        }
    };
    

Validator类

  • 定义一个cache存放所有的验证函数

  • //Validator类
    const Validator=function(){
        this.cache=[];
    }
    

Validator.prototype.add(dom,rules)——添加验证规则

  • 遍历rules数组,每个rule是由strategy和errMsg属性组成的对象

  • 取出每个rule的strategy('isNonEmpty'||'minLength:10')和errMsg属性值

  • 将每个验证函数(使用apply改变this指向dom)push进this.cache中,等到调用start()的时候再逐个调用

  • Validator.prototype.add=function(dom,rules){
        const self=this;
        for(let i=0,rule;rule=rules[i++];){
            (function(rule){
                const strategyAry=rule.strategy.split(':');
                const errMsg=rule.errMsg;
    
                self.cache.push(function(){
                    const strategy =strategyAry.shift();
                    strategyAry.unshift(dom.value);
                    strategyAry.push(errMsg);
                    return strategies[strategy].apply(dom,strategyAry);
                })
            })(rule);
        }
    }
    

Validator.prototype.start()——开启验证

  • 遍历this.cache,逐个验证,若errMsg有值则说明表单验证失败,返回错误信息errMsg

  • Validator.prototype.start=function(){
        for(let i=0,validatorFunc;validatorFunc=this.cache[i++];){
            var errMsg=validatorFunc();
            if(errMsg) return errMsg;
        }
    };
    

客户调用代码

  • <form action="#">
        用户名:<input type="text" name='userName'/>
        密码:<input type="text" name="password"/>
        手机号:<input type="text" name="phoneNumber">
        <button id='btn'>提交</button>
    </form>
    
  • const registerForm=document.querySelector('form');
    
    const validataFunc=function(){
        const validator=new Validator();
    
        //添加用户名验证
        validator.add(registerForm.userName,[{
            strategy:'isNonEmpty',
            errMsg:'用户名不能为空'
        }]);
    
        //添加密码验证
        validator.add(registerForm.password,[{
            strategy:'isNonEmpty',
            errMsg:'密码不能为空'
        },{
            strategy:'minLength:10',
            errMsg:'密码长度不能小于10位'
        }]);
    
        //添加手机号验证
        validator.add(registerForm.phoneNumber,[{
            strategy:'isNonEmpty',
            errMsg:'手机号不能为空'
        },{
            strategy:'isMobile',
            errMsg:'手机号格式错误'
        }]);
    
        const errMsg=validator.start();
        if(errMsg) return errMsg;
    
    }
    
    registerForm.onsubmit=function(){
        const errMsg=validataFunc();
        if(errMsg){
            alert(errMsg);
            return false;//阻止表单提交
        }
    }
    
策略模式的优缺点

优点:

  • 利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句
  • 提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,易于切换、易于理解、易于扩展
  • 策略模式中的算法也可以复用在其他地方,避免多重赋值粘贴
  • 利用组合和委托让Context拥有执行算法的能力,也是继承的一种轻便的替代方案

缺点:

  • 程序中增加了许多策略类和策略对象(实际上比把它们负责的逻辑堆砌在Context中要好)
  • 要使用策略模式,必须了解虽有的strategy,strategy要向客户暴露它所有的实现,这是违反最少知识原则的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值