设计模式: 5.1策略模式

254 阅读2分钟
---
title: 设计模式: 5.1策略模式
date: 2018-10-15 23:45:32
tags: 设计模式
---
#设计模式: 5.1策略模式
>定义一系列算法,把他们一个个封装,并且使他们可以相互替换。

以下是演绎顺序:
需求: 需要一个根据绩效计算薪资的函数。A对应4倍薪资。
####那么第一版程序就出来了:
```
var calculateBonus = function(level, salary){
if(level == "A"){
return salary*4
}else if(level == "B"){
return salary*3
}
}
```
缺点:
1. 包含太多if-else语句会让代码难以维护。
2. 不方便扩展。
3. 如果需要重用计算金额的算法,就只能复制粘贴。
####然后就出现第二版了:使用组合函数重构代码
```
var levelA = function(salary){
return salary*4
}
var levelB = function(salary){
return salary*3
}
var calculate = function(level, salary){
if(level == "A"){
return levelA(salary)
}else if(level == "B"){
return levelB(salary)
}
}
```
缺点,虽然把算法重用了,但是依然没有解决if-else嵌套和扩展性问题。
####第三版,使用策略模式重构
要知道,策略模式的目的在于,将算法的使用与算法的实现分离开来
而基于策略模式的程序要包括两个方面,一是策略类,策略类封装了具体的算法,并且负责计算的过程。二是环境类,负责接受客户的请求,随后把请求委托给策略类,进行计算。要做到这一点,context就要维持对入参对象的引用。维持这个环境,维持这个状态,提供给策略类进行计算的条件。
以下给予传统面向对象语言的实现
```
// 等级(策略类)
var levelA = function(){}
levelA.prototype.calculate=function(salary){
return salary*4
}
var levelB = function() {}
levelB.prototype.calculate=function(salary){
return salary*3
}
// 奖金类
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)
}
```
####但是呢,其实js中,一切皆对象,js版本的策略模式就会很简单
以上的策略类可以直接用函数表示,所以更简单的方法就是把strategy直接定义成函数。
并且,context也没必要使用Bonus来表示,我们依然使用caculateBonus函数充当Context来接受用户的请求。
```
var strategy = {
"A" : function(salary){
return salary*4
},
"B" : function(salary){
return salary*3
}
}
var caculateBonus = function(level, salary){
return strategy[level](salary)
}
```
所以这个时候,回去看第一版的问题,都得到了解决。
1. ~~包含太多if-else语句会让代码难以维护~~
2. ~~不方便扩展。~~
3. ~~如果需要重用计算金额的算法,就只能复制粘贴。~~

**下一篇预告,会写具体的策略模式的用法**

另外: 第一次投稿希望不被喷。但是如果文章存在问题或者争议,希望您能及时帮忙指出 。



* * *
资料来源于:《javascript设计模式与开发实践》