当前位置: 首页 > news >正文

第五章、策略模式

第五章、策略模式

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

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

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

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

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

最初代码实现

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;

利用策略模式重构代码:

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

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类:

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); //把计算奖金的操作委托给对应的策略对象
}

调用:

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

Javascript版的策略模式

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

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熟悉,比如旅游规划,出行方式的选择:飞机、火车、驾车等细节。

相关文章:

  • win10开机黑屏,只有鼠标,解决方案
  • 【鸿蒙 HarmonyOS 4.0】状态管理
  • 【更换yarn的位置】解决yarn和nodejs不在同一盘下产生的某些命令应用失败问题
  • Python实战:xlsx文件的读写
  • [程序员] sipp运行时socket接收队列持续满载 - 文件系统访问慢
  • PostgreSQL 的实体化视图介绍
  • android 15
  • 服务器丢包的原因及解决方法
  • Vue30 自定义指令 函数式 对象式
  • react18加antd新手上路使用
  • Golang 并发 Channel的用法
  • 智慧物业信息管理系统平台及APP建设项目
  • 第2讲:C语言数据类型和变量
  • 代理模式笔记
  • 【坑】Spring Boot整合MyBatis,一级缓存失效
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • Codepen 每日精选(2018-3-25)
  • HTTP那些事
  • input的行数自动增减
  • javascript 总结(常用工具类的封装)
  • JAVA之继承和多态
  • nginx 负载服务器优化
  • Octave 入门
  • PhantomJS 安装
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Python学习之路16-使用API
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • windows-nginx-https-本地配置
  • 给第三方使用接口的 URL 签名实现
  • 关于Java中分层中遇到的一些问题
  • 聊聊directory traversal attack
  • 每天10道Java面试题,跟我走,offer有!
  • 入口文件开始,分析Vue源码实现
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 如何正确理解,内页权重高于首页?
  • 昨天1024程序员节,我故意写了个死循环~
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​linux启动进程的方式
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (第二周)效能测试
  • (三十五)大数据实战——Superset可视化平台搭建
  • (译)2019年前端性能优化清单 — 下篇
  • (转)iOS字体
  • (转)项目管理杂谈-我所期望的新人
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .net 设置默认首页
  • .net打印*三角形
  • .net反混淆脱壳工具de4dot的使用
  • @AliasFor注解
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [AIR] NativeExtension在IOS下的开发实例 --- IOS项目的创建 (一)
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用