一.策略模式
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无限膨胀
缺点:代码逻辑分散在各个类中,造成逻辑分散的问题
三.对比两种模式
相同点:这两种模式都只有一个上下文、一些策略类或者是状态类,上下文把请求委托给这些类来执行
不同点:这两种模式的目的是不同的;策略模式的策略类之间是相互平行平等的,而状态模式的状态类把状态和行为封装到一起,把逻辑实现封装到类中,状态之间的切换也早被规定完成.