前端设计模式——策略模式

文章介绍了策略模式的概念,它是用来封装一系列算法并使它们可以相互替换,目的是将算法的使用与实现分离开。通过策略模式可以避免大量if-else语句,提高代码可维护性和复用性。文中给出了两个示例,一是用于优化等级奖金计算的if-else逻辑,二是用于实现不同缓动效果的动画策略。
摘要由CSDN通过智能技术生成

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换(相互替换是相对于静态类型语言而言的。因为静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。当它们的真正类型被隐藏在接口后面时,它们才能被相互替换。 而在 JavaScript 这种类型模糊的语言中没有这种困扰,任何对象都可以被替换使用。因此,JavaScript表现为它们具有相同的目标和意图)。而他的目的就是将算法的使用与算法的实现分离开来。

而当我们写代码时,需要写一大堆的if-else语句时,就要考虑是否需要用策略模式了。通过策略模式,我们可以把策略从业务代码中抽离出来,未来扩展的话无需深入到业务代码修改,只需要新增需要的策略,不会使得业务代码变得越来越臃肿,也可以更好的服用代码。

策略模式分为两部分,第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类 Context,Context 接受客户的请求,随后把请求委托给某一个策略类。

案例1:去掉if-else

/**  一大堆的if-else  **/
//level 评级 basicBonus 基础奖金
const computeBonus(level, basicBonus) = () => {
	if(level === 'A') {
        return basicBonus * 1;
    } else if(level === 'B') {
        return basicBonus * 2;
    } else if(level === 'C') {
        return basicBonus * 3;
    } else if(level === 'D') {
        return basicBonus * 4;
    }
}
computeBonus('A', 1000);//1000

/** 策略模式改写 **/
//定义策略类
const strategies = {
    'A': function(basicBonus) {
        return basicBonus * 1;
    },
    'B': function(basicBonus) {
        return basicBonus * 2;
    },
    'C': function(basicBonus) {
        return basicBonus * 3;
    },
    'D': function(basicBonus) {
        return basicBonus * 4;
    },
}
//使用环境类
const computeBonus = (level, basicBonus) {
    return strategies[level](basicBonus);
}
computeBouns('A', 1000);//1000

案例2:表单验证

案例3:写动画

//(策略类)定义不同动作计算方法,分离这些方法出来,而不是用if-else一个个判断
//参数分别为动画已消耗的时间、小球原始位置、小球目标位置、动画持续的总时间
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; 
} 
}; 
var Animate = function( dom ){ 
 this.dom = dom; // 进行运动的 dom 节点
 this.startTime = 0; // 动画开始时间
 this.startPos = 0; // 动画开始时,dom 节点的位置,即 dom 的初始位置
 this.endPos = 0; // 动画结束时,dom 节点的位置,即 dom 的目标位置
 this.propertyName = null; // dom 节点需要被改变的 css 属性名
 this.easing = null; // 缓动算法
 this.duration = null; // 动画持续时间
};
//(环境类)动画动作
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 );
 } 
 }, 19 ); 
}; 
Animate.prototype.step = function(){ 
 var t = +new Date; // 取得当前时间
 if ( t >= this.startTime + this.duration ){ // (1) 
 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 属性值
}; 
Animate.prototype.update = function( pos ){ 
 this.dom.style[ this.propertyName ] = pos + 'px'; 
}; 
//创建节点并且使用动画
var div = document.getElementById( 'div' ); 
var animate = new Animate( div ); 
animate.start( 'left', 500, 1000, 'strongEaseOut' ); 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值