一.策略模式
1.定义:把一些小的算法,封装起来,使他们之间可以相互替换(把代码的实现和使用分离开来)
2.利用策略模式实现小方块缓动
html代码:
<div id="container" style="width:500px;margin:0 auto;background-color: silver;"> <div id="move" style="position: absolute;background-color:blue;width:20px;height:20px"></div> </div>
js代码:
var container = document.getElementById('container'); container.style.height = window.innerHeight +"px"; var tween = {//t动画已消耗时间、b原始位置、c目标位置、d持续时间 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; this.startTime = 0; this.startPos = 0; this.endPos = 0; this.duration = 0;//小球运动的时间 this.propertyName = null;//要改变的css属性,例如top,left this.easing=null;//缓动算法 }; animate.prototype.start = function(endPos,duration,propertyName,easing){ //记录开始位置,并设置定时器是否有要执行的步数 this.startTime = new Date(); this.startPos = this.dom.getBoundingClientRect()[propertyName]; this.endPos = endPos; this.duration = duration; this.propertyName = propertyName; this.easing = tween[easing]; var setTime = setInterval(function(){ if(this.step()){ clearsetInterval(setTime); } this.step(); }.bind(this),20) } animate.prototype.step = function(){//动画执行一步需要的操作 var t = +new Date(); if(t>this.startTime+this.duration){ this.update(this.endPos); return false; } var pos = this.easing(t-this.startTime,this.startPos,this.endPos,this.duration);//t动画已消耗时间、b原始位置、c目标位置、d持续时间 this.update(pos); } animate.prototype.update = function(pos){//更新div的css属性 if(pos > window.innerWidth || pos>window.innerHeight){ this.dom.style[this.propertyName] = this.endPos +'px'; return false; } this.dom.style[this.propertyName] = pos +'px'; } //调用 var move = document.getElementById('move'); var a = new animate(move); a.start(100,1000,'bottom','sineaseIn')
3.优缺点
优点:避免多重条件判断语句;遵循开放-封闭原则,具有较好的扩展性,便于切换;可复用性;
缺点:违背最少知识原则(向用户暴露所有的实现)
二.状态模式
1.定义:允许一个对象在其状态改变时改变他的行为,对象看起来视乎修改了他的类
2.状态模式例子:电源开关三种状态的互相变化(状态驱动行为)
var Light = function(){ this.offState = new offLightState(this); this.weakState = new weakLightState(this); this.strongState = new strongLightState(this); this.button = null; } Light.prototype.start = function(){ this.button = document.getElementById('change'); this.current = this.offState; this.button.onclick = function(){ this.current.btnPressed(); }.bind(this); } Light.prototype.setState = function(newState){//改变状态 this.current = newState; } //状态模式的关键是把每种状态都封装成一个类 var offLightState = function(light){ this.light = light; }; offLightState.prototype.btnPressed = function(){ console.log('调弱'); this.light.setState(this.light.weakState); } var weakLightState = function(light){ this.light = light; }; weakLightState.prototype.btnPressed = function(){ console.log('调强'); this.light.setState(this.light.strongState); } var strongLightState = function(light){ this.light = light; }; strongLightState.prototype.btnPressed = function(){ console.log('关闭'); this.light.setState(this.light.offState); } var light = new Light(); light.start();//调弱 调强 关闭
3.状态模式是状态机的一种实现方式,还可以直接将状态委托给字面量,利用Function.prototype.call()调用,达到和状态模式一样的效果
var FMC = { on:{ buttonWasPressed:function(){ console.log('变弱') this.current = FMC.weak; } }, weak:{ buttonWasPressed:function(){ console.log('变强') this.current = FMC.strong; } }, strong:{ buttonWasPressed:function(){ console.log('变更强') this.current = FMC.superstrong; } }, superstrong:{ buttonWasPressed:function(){ console.log('关闭') this.current = FMC.off; } }, off:{ buttonWasPressed:function(){ console.log('打开') this.current = FMC.on; } } } var light = function(){ this.current = FMC.off; this.button = null; } light.prototype.start = function(){ this.button = document.getElementById('change'); console.log("current",this.current) this.button.onclick = function(){ this.current.buttonWasPressed.call(this); }.bind(this); } var l = new light(); l.start();
4.优缺点
优点:可扩展性较好,可以方便的增加新的状态;相比冗余的if else判断,状态模式将逻辑封装在类中,避免Context无限膨胀
缺点:代码逻辑分散在各个类中,造成逻辑分散的问题
三.对比两种模式
相同点:这两种模式都只有一个上下文、一些策略类或者是状态类,上下文把请求委托给这些类来执行
不同点:这两种模式的目的是不同的;策略模式的策略类之间是相互平行平等的,而状态模式的状态类把状态和行为封装到一起,把逻辑实现封装到类中,状态之间的切换也早被规定完成.