首页 > 代码库 > JavaScript设计模式与开发实践---读书笔记(5) 策略模式

JavaScript设计模式与开发实践---读书笔记(5) 策略模式

策略模式的定义是:定义一系列的算法,把它们一个个封转起来,并且使它们可以相互替换。

JavaScript版本的策略模式:

奖金系统:

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‘,20000));//输出:80000    console.log(calculateBonus(‘A‘,10000));//输出:30000

使用策略模式实现缓动动画:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>小球运动策略模式</title>    <style>        #div{            position: absolute;            background: blue;            width:50px;            height: 50px;        }    </style></head><body>    <div id="div">我是小球</div></body></html><script>    var tween = {        linear: function(t,b,c,d){            return c*t/d+b;        },        easeIn: function(t,b,c,d){            return c*(t/=d)*t+b;        },        strongEaseIn: function(t,b,c,d){            return c*(t/=d)*t*t*t*t+b;        },        strongEaseOut: function(t,b,c,d){            return c*((t=t/d-1)*t*t*t*t+1)+b;        },        sineaseIn: function(t,b,c,d){            return c*(t/=d)*t*t+b;        },        sineaseOut: function(t,b,c,d){            return c*((t=t/d-1)*t*t+1)+b;        }    };    var Animate = function(dom){        this.dom = dom;//进行运动的dom节点        this.startTime = 0;//动画开始时间        this.startPos = 0;        this.endPos = 0;        this.propertyName = null;        this.easing = null;        this.duration = null;    };    Animate.prototype.start = function(propertyName,endPos,duration,easing){    //启动这个动画        this.startTime = +new Date;        this.startPos = this.dom.getBoundingClientRect()[propertyName];//dom初始节点位置        this.propertyName = propertyName;//dom节点需要被改变的CSS属性名        this.endPos = endPos;//dom节点目标位置        this.duration = duration;//动画持续事件        this.easing = tween[easing];//缓动算法        var self = this;        var timeId = setInterval(function(){            if(self.step()===false){                clearInterval(timeId);            }        },19)    };    Animate.prototype.step = function(){  //代表小球运动的每一帧要做的事情        var t = +new Date;        if(t>=this.startTime+this.duration){//修正小球位置            this.update(this.endPos);//更新小球的CSS属性值            return false;        }        var pos = this.easing(t-this.startTime,this.startPos,this.endPos-this.startPos,this.duration);        this.update(pos);//更新小球的CSS属性值    };    Animate.prototype.update = function(pos){        this.dom.style[this.propertyName] = pos+‘px‘;    };    var div = document.getElementById(‘div‘);    var animate = new Animate(div);    animate.start(‘left‘,500,1000,‘strongEaseOut‘);    //animate.start(‘top‘,1500,500,‘strongEaseIn‘);</script>

策略模式指的是定义一系列的算法,并且把它们封装起来。
表单验证:

校验逻辑:

  • 用户名不能为空
  • 密码长度不能少于6位
  • 手机号码必须符合格式
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>策略模式表单验证</title></head><body>    <form action="" id="registerForm" method="post">        请输入用户名:<input type="text" name="userName">        请输入密码:<input type="text" name="password">        请输入手机号码:<input type="text" name="phoneNumber">        <button>提交</button>    </form></body></html><script>    var strategies = {        isNonEmpty: function(value,errorMsg){//不为空            if(value =http://www.mamicode.com/== ‘‘){                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){                var strategyAry = rule.strategy.split(‘:‘);                var errorMsg = rule.errorMsg;                self.cache.push(function(){                    var strategy = strategyAry.shift();                    strategyAry.unshift(dom.value);                    strategyAry.push(errorMsg);                    return strategies[strategy].apply(dom,strategyAry);                });            })(rule)        }    };    Validator.prototype.start = function(){        for(var i=0,validataFunc;validataFunc = this.cache[i++]; ){            var errorMsg = validataFunc();            if(errorMsg){                return errorMsg;            }        }    };    //用户调用代码    var registerForm = document.getElementById(‘registerForm‘);    var validataFunc = function(){        var validator = new validator();//创建一个validator对象        validator.add(registerForm.userName,[{            strategy:‘isNonEmpty‘,            errorMsg:‘用户名不能为空‘        },{            strategy:‘minLength:6‘,            errorMsg:‘用户名长度不能小于6位‘        }]);        validator.add(registerForm.password,[{            strategy:‘minLength:6‘,            errorMsg:‘密码长度不能小于6位‘        }]);        validator.add(registerForm.phoneNumber,[{            strategy:‘isMobile‘,            errorMsg:‘手机号码格式不正确‘        }]);        var errorMsg = validator.start();        return errorMsg;    };    registerForm.onsubmit = function(){        var errorMsg = validataFunc();        if(errorMsg){            alert(errorMsg);            return false;        }    };</script>

策略模式的一些优点:
策略模式利用组合、委托和多态等技术思想,可以有效地避免多重条件选择语句。

策略模式提供了对开放-封闭原则的完美支持,将算法封装在独立的startegy中,使得它们易于切换,易于理解,易于扩展。

策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制性粘贴工作。

在策略模式中利用组合和委托让Context拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

 

在JavaScript语言的策略模式中,策略类往往被函数所代替,这时策略模式就是一种"隐形"的模式。

 

JavaScript设计模式与开发实践---读书笔记(5) 策略模式