js策略模式vs狀態模式

一.策略模式

1.定義:把一些小的算法,封裝起來,使他們之間能夠相互替換(把代碼的實現和使用分離開來)
2.利用策略模式實現小方塊緩動css

html代碼: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.優缺點
優勢:避免多重條件判斷語句;遵循開放-封閉原則,具備較好的擴展性,便於切換;可複用性;
缺點:違背最少知識原則(向用戶暴露全部的實現)dom

二.狀態模式

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()調用,達到和狀態模式同樣的效果this

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無限膨脹
缺點:代碼邏輯分散在各個類中,形成邏輯分散的問題prototype

三.對比兩種模式

相同點:這兩種模式都只有一個上下文、一些策略類或者是狀態類,上下文把請求委託給這些類來執行
不一樣點:這兩種模式的目的是不一樣的;策略模式的策略類之間是相互平行平等的,而狀態模式的狀態類把狀態和行爲封裝到一塊兒,把邏輯實現封裝到類中,狀態之間的切換也早被規定完成.code

相關文章
相關標籤/搜索