zoukankan      html  css  js  c++  java
  • 第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')
    	
    

      

  • 相关阅读:
    BAPI_TRANSACTION_COMMIT的使用方法(转)
    Win7 64bit系统下未能加载文件或程序集“System.Data.SQLite”的解决办法
    在Windows XP环境中配置OPC服务器时的设置方式
    关于异常“The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine”的处理
    MSChart使用做折线图饼图(转)
    C#如何导入内文至SAP(转)
    经典Sql大全转
    工程师突击:SAP ABAP实用程序开发攻略(转)
    如何使用ExtJS Design中生成的代码
    ExtJS 4 学习(1)环境配置及注意点
  • 原文地址:https://www.cnblogs.com/huyanluanyu/p/9984623.html
Copyright © 2011-2022 走看看