第五章、策略模式

第五章、策略模式

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

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

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,第二个部分是环境类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熟悉,比如旅游规划,出行方式的选择:飞机、火车、驾车等细节。
相关推荐
tiger从容淡定是人生2 天前
可审计性:AI时代自动化测试的核心指标
人工智能·自动化·项目管理·策略模式·可用性测试·coo
都说名字长不会被发现3 天前
模版方法 + 策略模式在库存增加/扣减场景下的应用
策略模式·模板方法模式·宏命令·策略聚合·库存设计
默|笙3 天前
【Linux】进程概念与控制(2)_进程控制
java·linux·策略模式
枫叶林FYL4 天前
Agent/Teakenote 系统(Swarm 架构)深度技术报告
架构·策略模式
苏渡苇5 天前
枚举的高级用法——用枚举实现策略模式和状态机
java·单例模式·策略模式·枚举·状态机·enum
harder3217 天前
Swift 面向协议编程的 RMP 模式
开发语言·ios·mvc·swift·策略模式
skywalk81638 天前
esxi8 虚拟机中怎么安装mac os(纯AI回答,未实践)
策略模式·esxi
廖圣平8 天前
从零开始,福袋直播间脚本研究【八】《策略模式》
开发语言·python·bash·策略模式
爱学习 爱分享12 天前
简单工厂模式和策略模式的区别
简单工厂模式·策略模式
xcntime15 天前
Python中print函数如何实现不换行输出?
策略模式