设计模式之二:策略模式

策略模式的定义:分别分装行为为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象,原则就是分离变化部分,分装接口,基于接口编程各种功能,此模式让行为算法的变化独立于算法的使用者

 
策略模式指的是定义一些列的算法,把他们一个个封装起来,目的就是将算法的使用与算法的实现分离开来。
以策略模式的思路实现上边例子的效果的js代码:
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;
     }
 };

2. HTML 部分

<</span>div style="position: relative;border: 1px solid #ff0000; width: 560px;min-height: 30px">
 2         <</span>div style="position:absolute;background:rgba(0,0,255,.3);width: 60px;line-height: 30px;" id="div">我是 div</</span>div>
 3     </</span>div>
 4     <</span>div>
 5         <</span>label><</span>input type="radio" name="tween" value="linear" checked="checked">linear</</span>label>
 6         <</span>label><</span>input type="radio" name="tween" value="easeIn">easeIn</</span>label>
 7         <</span>label><</span>input type="radio" name="tween" value="strongEaseIn">strongEaseIn</</span>label>
 8         <</span>label><</span>input type="radio" name="tween" value="strongEaseOut">strongEaseOut</</span>label>
 9         <</span>label><</span>input type="radio" name="tween" value="sineaseIn">sineaseIn</</span>label>
10         <</span>label><</span>input type="radio" name="tween" value="sineaseOut">sineaseOut</</span>label><</span>br/>
11         <</span>input type="button" id="btnRun" value="run">
12     </</span>div>
3. 定义一个构造函数接收一个参数:即将运动起来的dom节点

 var Animate = function( dom ){
     this.dom = dom; // 进行运动的 dom 节点
     this.startTime = 0; // 动画开始时间
      this.startPos = 0; // 动画开始时, dom 节点的位置,即 dom 的初始位置
      this.endPos = 0; //
      this.propertyName = null; // dom 节点需要被改变的 css 属性名
     this.easing = null; // 缓动算法
     this.duration = null; // 动画持续时间
};
4. 启动方法,负责启动这个动画
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);
        }
    },20);
 };
5. 动画定时器运行的步骤,setp方法,节点运动的每一帧要做的事情

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);
    // pos 为节点当前位置
    this.update( pos ); // 更新节点的 CSS 属性
};
6. 更新节点的CSS属性值
Animate.prototype.update = function(pos){
     this.dom.style[ this.propertyName ] = pos + "px";
 };
7. 测试运行
var div = document.getElementByIdx_x_x("div");
    var animate = new Animate(div);
    // 设置运行事件
    var btnRun = document.getElementByIdx_x_x("btnRun");
    var radios = document.getElementsByName("tween"); // 获取单选框
    btnRun.onclick = function(){
        for(var i= 0,lengh=radios.length;i){
            // 查找被选中要执行的算法策略
            if(radios[i].checked){
                animate.reset(); // 重置节点运动属性
                // 设置动画的基本属性
                animate.start( "left", 500, 1000, radios[i].value);
                break;
            }
        }
    };
8. 重置节点的CSS属性为0,reset()方法

Animate.prototype.reset = function(){
        // 重置为 0
    this.dom.style[this.propertyName] = "0px";
};
策略模式总结:
分析项目中变化与不变化的部分
多用组合,而不是继承,用行为的组合,而不是行为的继承,更有弹性
策略模式的优点:
  1. 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句
  2. 策略模式提供了对开放-封闭原则的完美支持,将算法封装在独立的 strategy 中,使得它们易于切换,易于理解,易于扩展
策略模式的缺点:
  1. 会在程序中增加许多策略类或者策略对象,但实际上比把他们负责的逻辑堆砌在 Context 中要好
  2. 使用策略模式,必须了解所有的策略,才能更好的选择一个合适的策略

阅读参考书籍 - << JavaScript 设计模式与开发实践 >>
缓动算法 - javascript Tween算法及效果
posted @ 2016-07-01 16:57  灬東歌℡  阅读(143)  评论(0)    收藏  举报