第五章、策略模式

第五章、策略模式

定义:定义一些列算法,把他们一一封装,并且他们可以相互替换。

核心:将算法的实现和算法的使用分离

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,第二个部分是环境类Context。

  • 策略类:策略类封装了具体的算法,并负责具体的计算过程。
  • 环境类Context:环境类Context接受客户的请求,随后把请求委托给某一个策略类。

案例:计算奖金,绩效分别为S、A、B,奖金分别为4、3、 2倍;

最初代码实现

js 复制代码
var calculateBunus = function(preformancelevel, salary) {
    if(preformancelevel === 'S') {
        return salary * 4;
    }
    if(preformancelevel === 'A') {
        return salary * 3;
    }
    if(preformancelevel === 'B') {
        return salary * 2;
    }
}
calculateBunus('B', 2000) // 4000;
calculateBunus('S', 4000) // 16000;
  • 代码简单明了,但缺点也显而易见:
    calculateBunus函数比较庞大,包含了很多if-else语句,这些语句需要覆盖所有逻辑的分支。
  • calculateBunus函数缺乏弹性,如果新增一个"C"字段,或者把"S"的奖金系数改为5倍,必须在calculateBunus函数内部修改,这样就违反了开放-封闭的原则。
  • 算法的复用性差,如果程序中其他地方需要重用这些计算奖金的算法呢?只能CTRL+CV;

利用策略模式重构代码:

我们把所有的绩效以及奖金分别写成单独的函数

js 复制代码
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类:

js 复制代码
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() { //取得奖金数额
    if(!this.strategy) {
        throw new Error('未设置'strategy属性');
    }
    return this.strategy.calculate(this.salary); //把计算奖金的操作委托给对应的策略对象
}

调用:

js 复制代码
var bonus = new Bonus();
bonus.setSalary(1000);
bonus.setStrategy(new performanceS()); //设置策略对象
console.log(bonus.getBonus()) //输出:4000

Javascript版的策略模式

上面所说的是让strategy对象从各个策略类中创建而来,在js中,可以把strategy直接定义成函数:

javascript 复制代码
var strategies = {
	"S":function(salary) {
        return salary * 4;
    }
    "A":function(salary) {
        return salary * 3;
    }
	"B":function(salary) {
        return salary * 2;
    }
};
//同样Context也没必要定义成Bonus类来表示,依然用calculateBonus函数充当Context来接收客户请求
var calculateBonus = function(level, salary) {
    return strategies[level](salary);
}
console.log(calculateBonus('S',20000))  //输出:80000
console.log(calculateBonus('A',10000))  //输出:30000

策略模式的优缺点

  • 策略模式利用组合、委托、和多态等技术和思想,可以有效地避免多重条件选择语句。
  • 策略模式提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,使得他们易于切换,易于理解易于扩展
  • 策略模式中的算法也可以复用在系统的其他地方,复用性高。
  • 在策略模式中利用组合和委托来让Context拥有执行算法的能力,也是继承的一种更轻便的替代方案

缺点:

  • 使用策略模式会在程序中增加许多策略类和策略对象,但实际上这比把它们负责的逻辑堆砌在Context中要好
  • 另外,还需要对strategy熟悉,比如旅游规划,出行方式的选择:飞机、火车、驾车等细节。
相关推荐
gjh120810 小时前
设计模式:工厂方法模式和策略模式
设计模式·工厂方法模式·策略模式
liang899913 小时前
设计模式之策略模式(Strategy)
设计模式·策略模式
修道-032314 小时前
【JAVA】二、设计模式之策略模式
java·设计模式·策略模式
Jack黄从零学c++2 天前
设计模式——策略模式(c++)
c++·设计模式·策略模式
南城花随雪。3 天前
Spring框架之策略模式 (Strategy Pattern)
java·spring·策略模式
Fre丸子_3 天前
设计者模式之策略模式
c++·策略模式
超越不平凡3 天前
Spring Plugin与策略模式:打造动态可扩展的应用
spring·策略模式·spring plugin
G皮T3 天前
【设计模式】行为型模式(二):策略模式、命令模式
java·设计模式·策略模式·命令模式·command·strategy
7年老菜鸡6 天前
策略模式(C++)三分钟读懂
c++·qt·策略模式
也无晴也无风雨7 天前
代码中的设计模式-策略模式
设计模式·bash·策略模式