第五章、策略模式

第五章、策略模式

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

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

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,第二个部分是环境类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熟悉,比如旅游规划,出行方式的选择:飞机、火车、驾车等细节。
相关推荐
意法半导体STM3212 天前
【官方原创】如何为STM32CubeMX2配置Visual Studio Code配置方案
vscode·stm32·单片机·嵌入式硬件·策略模式·stm32cubemx·嵌入式开发
山东点狮信息科技有限公司12 天前
企业级 MES 制造执行系统架构设计与实践
spring cloud·性能优化·系统架构·策略模式·点狮
zzqssliu13 天前
基于策略模式与责任链的代购商品多源采集架构实战
架构·策略模式
mxpan13 天前
macOS 13+ 上使用 macFUSE + NTFS-3G 读写 NTFS 移动硬盘技术说明
macos·策略模式
折哥的程序人生 · 物流技术专研14 天前
Java 23 种设计模式:从踩坑到精通 | 番外:编排器+策略模式在多平台电子面单中的实战(含性能压测)
设计模式·策略模式·代码重构·java设计模式·编排器·电子面单·从踩坑到精通
忧云14 天前
2026年最新 Cursor 国内使用 DeepSeek API等各模型使用完整教程
ai编程·策略模式·cursor·byok·cursor使用国内大模型
AIex-YH15 天前
三域贯通11/12:生物制造的“死亡之谷“,CDMO 是桥还是船?
运维·制造·策略模式
回忆2012初秋15 天前
【Nginx】原理、配置与运维实战(2)
运维·nginx·策略模式
怎么没有名字注册了啊16 天前
macOS 基于 CSDN GitCode + Homebrew Tap 发布 Qt .app 二进制程序通用教程(homebrew 安装自己的软件)
策略模式·homebrew·formula·ruhy
坏小虎17 天前
macOS 安装 Ghostty 终端完整教程:环境、依赖与美化配置
macos·策略模式