第5章 策略模式
第二部分 设计模式
第5章 策略模式
定义:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
其实就是定义一系列的算法,把他们各自封装成策略类,算法被封装在策略类内部的方法里。在对Context发起请求的时候,Context总是把请求委托给这些策略对象中间的某一个进行计算。
5.1 使用策略模式计算奖金
/**
* 使用策略模式计算奖金
* S 4个月奖金
* A 3个月奖金
* B 2个月奖金
*/
//1、最原始实现方式
//缺点:
//(1)calculate函数比较庞大,包含了很多判断语句,这些语句必须包含所有的逻辑分支
//(2)函数缺乏弹性,如果增加了新的绩效等级,或者想把绩效等级的奖金系数修改一下,我们必须深入calculate函数内部实
//现违反了开放-封闭原则
//算法的复用性差,如果在程序的其它地方用到这些算法,我们只能复制粘帖
var calculateBonus = function(performanceLevel, salary){
switch(performanceLevel){
case 'S':
return salary*4
break
case 'A':
return salary*3
break
case 'B':
return salary*2
break
default:
return salary
break
}
}
console.log(calculateBonus('A',10000))
//2、使用组合函数重构代码
//优点:(1)把各种算法封装到一个个的小函数里,可以一目了然的知道对应的哪种算法
//(2)复用性强
//缺点:calculateBouns函数会越来越庞大,在系统变化的时候缺乏弹性
var performanceS = function(salary){
return salary*4
}
var performanceA = function(salary){
return salary*3
}
var performanceB = function(salary){
return salary*2
}
var calculateBonus = function(performanceLevel, salary){
switch(performanceLevel){
case 'S':
return performanceS(salary)
break
case 'A':
return performanceA(salary)
break
case 'B':
return performanceB(salary)
break
}
}
console.log(calculateBonus('B',10000))
//3、使用策略模式重构代码,将不变的部分和变化的部分隔离开来,策略模式的目的就是将算法的使用和
//算法的实现分离开来。
//一个基于策略模式的程序至少由两部分组成。
//第一部分是策略类,策略类封装了具体的算法,并负责具体的计算过程。
//第二部分是环境类Context,Context接收用户的请求,随后把请求委托给某一个策略类。
//把每种绩效的计算规则都封装在对应的策略类里面
var performanceS = function(){}
performanceS.prototype.calculate = function(salary){
return salary*4
}
var performanceA = function(){}
performanceA.prototype.calculate = function(salary){
return salary*3
}
var performanceB = function(){}
performanceB.prototype.calculate = function(salary){
return salary*2
}
//定义奖金类Bonus
var Bonus = function(){
this.salary = null
this.strategy = null
}
Bonus.prototype.setSalary = function(salary){
this.salary = salary
}
Bonus.prototype.setStrategy = function(strategy){
this.strategy = strategy
}
Bonus.prototype.getBonus = function(){
return this.strategy.calculate(this.salary)
}
var bonus = new Bonus()
bonus.setSalary(10000)
bonus.setStrategy(new performanceS())//设置策略对象
console.log(bonus.getBonus())
5.2 JavaScript中函数形式的策略模式
//javaScript中函数形式的策略模式
var strategy = {
'S': function(salary){
return salary*4
},
'A': function(salary){
return salary*3
},
'B': function(salary){
return salary*2
}
}
var calculateBonus = function(level,salary){
return strategy[level](salary)
}
console.log(calculateBonus('A',10000))
5.3 使用策略模式实现缓动动画
<div id="div" style="position: absolute;background: blue">我是DIV</div>
/**
* [tween 动画缓动的算法]
* @type {Object}
* t 动画已消耗时间
* b 原始位置
* c 目标位置
* d 动画持续时间
*/
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;
}
}
/**
* [Animate description]
* @param {[type]} dom [description]
*/
var Animate = function(dom){
this.dom = dom //进行运动的dom节点
this.startTime = 0 //动画开始时间
this.startPos = 0 //动画开始时dom节点的初始位置
this.endPos = 0 //动画结束时dom节点的目标位置
this.propertyName = null //dom节点需要改变的css属性
this.easing = null //缓动算法
this.duration = null //动画持续时间
}
/**
* [start 动画启动]
* @param {[type]} propertyName [dom节点需要改变的css属性,如left、right、top]
* @param {[type]} endPos [动画结束时dom节点的目标位置]
* @param {[type]} duration [动画持续时间]
* @param {[type]} easing [缓动算法]
* @return {[type]} [description]
*/
Animate.prototype.start = function(propertyName, endPos, duration, easing){
this.startTime = +new Date() //获取当间时间
//getBoundingClientRect获取元素位置
this.startPos = this.dom.getBoundingClientRect()[propertyName] //dom节点初始位置
this.propertyName = propertyName
this.endPos = endPos
this.duration = duration
this.easing = tween[easing]
var self = this
//启动定时器,开始执行动画
var timeId = setInterval(function(){
//如果动画结束清除定时器
if(self.step() === false){
clearInterval(timeId)
}
},19)
}
/**
* [step 动画运动的每一帧要做的事]
* @return {[type]} [description]
*/
Animate.prototype.step = function(){
var t = +new Date() //取得当前时间
if(t >= this.startTime + this.duration){
this.update(this.endPos)
return false
}
//dom当前位置
var pos = this.easing(t - this.startTime, this.startPos, this.endPos, this.duration)
//更新dom当前位置信息
this.update(pos)
}
/**
* [update 更新动画运动的位置]
* @param {[type]} pos [当前动画的位置]
* @return {[type]} [description]
*/
Animate.prototype.update = function(pos){
this.dom.style[this.propertyName] = pos + 'px'
}
var div = document.getElementById('div')
var animate = new Animate(div)
animate.start('right',500, 1000, 'easeIn')
浙公网安备 33010602011771号