3

一.策略模式

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无限膨胀
缺点:代码逻辑分散在各个类中,造成逻辑分散的问题

三.对比两种模式

相同点:这两种模式都只有一个上下文、一些策略类或者是状态类,上下文把请求委托给这些类来执行
不同点:这两种模式的目的是不同的;策略模式的策略类之间是相互平行平等的,而状态模式的状态类把状态和行为封装到一起,把逻辑实现封装到类中,状态之间的切换也早被规定完成.


Delia
75 声望3 粉丝

路漫漫其修远兮,吾将上下而求索。