设计模式之策略模式

一、策略模式的定义和初步使用

1.引入

​ 策略模式的定义是:“定义一系列的算法,把他们封装起来,并实现可以相互替换”。也就是说我们实现一个功能可能有多种算法,我们一般会根据不同的场景去选择不同的算法。这个定义说的并不是很清楚,我们可以根据下面的例子来说明这个模式。

​ 比如我们现在要实现不同员工根据他们平时业绩表现来决定他们的薪水情况,常规的情况下我们会写出下面的算法:

1
2
3
4
5
6
7
8
9
10
11
12
function calculate(level,salery){
if(level == 'S'){
salery = salery * 4;
}else if(level == 'A'){
salery = salery * 2;
}else{
salery = salery;
}
return salery
}
console.log(calculate('S',1000))
console.log(calculate('A',500))

​ 上面的算法执行的结果是没有问题的,但是仔细分析我们可以发现上面的代码实际上并不符合绝大部分用户要求,原因有如下几点:

  1. 上述代码的if-else语句过多,导致逻辑的覆盖面需要很广泛,否则不能将所有的情况覆盖到
  2. 上面的代码中,如果之后有更多的等级需要覆盖,或者某个等级的策略有变化,我们需要深入到calculate这个函数中去,这丫昂违背了开放-封闭的原则。
  3. 这个算法复用性不好,如果其他地方有需要用并稍稍有点修改,就需要去复制粘贴一大段代码,重复代码较多。

​ 基于以上的分析,我们需要对上述代码进行修正,运用策略模式使代码更加规范。

2.使用策略模式重构代码

​ 首先我们需要明确策略模式的原则,就是定义一系列的算法,并实现他们的封装,并且让算法的使用和算法的实现分离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
定义几个策略
*/
var levelS = function(){}
levelS.prototype.calculate = function(salery){
return salery * 4
}
var levelA = function(){}
levelA.prototype.calculate = function(salery){
return salery * 2
}
var levelB = function(){}
levelB.prototype.calculate = function(salery){
return salery * 0.5
}
/*
实现奖金类
*/
var Salery = function(){
this.salery = null;
this.strategy = null;
}
Salery.prototype.setSalery = function(salery){
this.salery = salery
}
Salery.prototype.setStrategy = function(strategy){
this.strategy = strategy
}
Salery.prototype.getSalery = function(){
return this.strategy.calculate(this.salery)
}

//进行测试
var me = new Salery();
me.setSalery(50000);
me.setStrategy(new levelS())
console.log(me.getSalery())

​ 这段代码中将不同策略的定义和策略的实现放在了两个不同的地方分来执行。当我们在实现类中执行这个方法的时候,实际上是将需要的策略类型实例化并传给setStrategy这样的函数,从而实现了对实现类策略的设置。当我们需要去执行这个策略的时候,实现类就会去调取之前我们定义的策略类,委托给他去执行。下一次如果是一个不一样的策略的时候,只需要在setStrategy里面传入不同的参数即可。这样就实现了我们之前那所说的算法之间可以相互替换。策略类和实现类分离。当然,这里我们主要使用的是面向对象的写法来实现这个功能,接下来尝试用JavaScript的特性来实现这个功能。

二、JavaScript实现策略模式

​ 在上面的例子里面,我们是把不同的策略按照不同的对象来实现的。在JavaScript里面,我们还可以运用JavaScript的特点来实现这个功能。在一个类中将整个策略列举出来,用键代表策略的名,值就是策略的具体内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var strategies = {
"S":function(salery){
return salery * 4
},
"A":function(salery){
return salery * 2
},
"B":function(salery){
return salery * 0.5
}
}

var calculate = function(level,salery){
return strategies[level](salery)
}

console.log(calculate('S',10000))
console.log(calculate('A',10000))

​ 很明显,利用这种方式来实现明显从代码简洁度上要好很多,直接将策略类型在strategies里面罗列出来,并在calculate里面通过键找到对应的策略并执行相应的方法。于是整个策略执行完成。

三、具体应用与实例

​ (待更新)

0%