摘要:本系列为设计模式与开发实践作者曾探学习总结,如想深入了解,请支持作者原版策略模式策略模式的定义定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。
本系列为《JavaScript设计模式与开发实践》(作者:曾探)学习总结,如想深入了解,请支持作者原版
策略模式策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。
举个形象的例子,使用策略模式计算奖金。
业务需求:
绩效为S的人年终奖有4倍工资
绩效为A的人年终奖有3倍工资
绩效为B的人年终奖有2倍工资
财务部希望我们可以提供一段代码,方便他们计算员工的年终奖。
最初的代码实现我们可以编写一个名为calculateBonus的函数来计算员工的奖金数额,这个函数需要传入两个参数:工资数额和绩效等级。代码如下:
var calculateBonus = function(performanceLevel, salary) { if (performanceLevel === "S") { return salary * 4; } if (performanceLevel === "A") { return salary * 3; } if (performanceLevel === "B") { return salary * 2; } }; calculateBonus("B", 20000); //輸出:40000 calculateBonus("S", 6000); //輸出:24000
可以发现,这段代码非常简单,但是存在着显而易见的缺点。
calculateBonus函数比较庞大,包含了很多if语句,这些语句需要覆盖所有的逻辑分支
calculateBonus函数缺乏弹性,如果增加新的绩效等级,那我们必须深入calculateBonus内部,违反了开放-封闭原则
算法的复用性差,如果在程序的其他地方需要重用这些计算奖金的算法,我们的选择只有复制和粘贴
因此,我们要重构这段代码。
使用组合函数重构代码我们把各种算法封装到一个个小函数里面:
var performanceS = function(salary) { return salary * 4; } var performanceA = function(salary) { return salary * 3; } var performanceB = function(salary) { return salary * 2; } var calculateBonus = function(performanceLevel, salary) { if (performanceLevel == "S") { return performanceS(salary); } if (performanceLevel == "A") { return performanceA(salary); } if (performanceLevel == "B") { return performanceB(salary); } }; calculateBonus("A", 10000);//輸出:30000
我們的程序得到了一定的改善,但我們依然沒有解決最重要的問題:calculateBonus函數有可能越來越龐大,而且在系統變化的時候缺乏彈性。
使用策略模式重構代碼将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成,第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二部分是环境类Context接受客户的请求,随后把请求委托给某一个策略类。
现在我们用策略模式来重构上边的代码。
//我们先把每种绩效的计算规则封装在对应的策略类里 var porformanceS = function() {}; porformanceS.prototype.calculate = function(salary) { return salary * 4; }; var porformanceA = function() {}; porformanceA.prototype.calculate = function(salary) { return salary * 3; }; var porformanceB = function() {}; porformanceB.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() { return this.strategy.calculate(this.salary); }
在完成最終的代碼之前,我們再來回顧一下策略模式的思想:
定義一系列的算法,把它們一個個封裝起來,並且使它們可以互相替換。
如果说的更详细一点,就是:定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。在客户对Context发起请求的时候,Context总是把请求委托给这些策略对象中的某一个进行计算。
我们继续完成刚才的代码:
var Bonus = new Bonus(); bonus.setSalary(1000); bonus.setStrategy(new performanceS()); bonus.getBonus();JavaScript版本的策略模式
上述代码是模拟了一些传统的面向对象语言的实现,实际上在JavaScript中,函数也是对象,所以更简单和直接的做法是把strategy直接定义为函数:
var strategies = { "S": function ( salary ){ return salary * 4; }, "A": function ( salary ){ return salary * 3; }, "B": function ( salary ){ return salary * 2; } }; var calculateBonus=function(level,salary){ return strategies[level](salary); };总结
在JavaScript语言中,策略类往往被函数所替代,这是策略模式就成为了一种隐形的模式。尽管这样,彻底了解策略模式,也有助于我们明白使用函数的好处。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78857.html
摘要:前端每周清单第期现状分析与优化策略单元测试爬虫作者王下邀月熊编辑徐川前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点分为新闻热点开发教程工程实践深度阅读开源项目巅峰人生等栏目。 showImg(https://segmentfault.com/img/remote/1460000011008022); 前端每周清单第 29 期:Web 现状分析与优化策略...
摘要:设计模式与开发实践读书笔记。策略模式可以有效避免多重条件选择语句。当然,策略模式也有一些缺点增加了许多策略类或者策略对象。要使用策略模式,必须了解所有的,违反了最少知识原则。至此,回家咯附设计模式之发布订阅模式观察者模式 《JavaScript设计模式与开发实践》读书笔记。这本书挺好的,推荐。 俗话说,条条大路通罗马。在现实生活中,我们可以采用很多方法实现同一个目标。比如我们先定个小目...
摘要:策略模式可以避免代码中的多重判断条件。策略模式在程序中或多或少的增加了策略类。此文仅记录本人阅读设计模式与开发实践这个本时的感受,感谢作者曾探写出这么好的一本书。设计模式中很重要的一点就是将不变和变分离出来。参考设计模式与开发实践曾探 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且是它们可以相互替换。 策略模式可以避免代码中的多重判断条件。 策略模式很好的体现了开放-...
摘要:做前端开发已经好几年了,对设计模式一直没有深入学习总结过。今天第一天,首先来讲策略模式。什么是策略模式四兄弟的经典设计模式中,对策略模式的定义如下定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。 做前端开发已经好几年了,对设计模式一直没有深入学习总结过。随着架构相关的工作越来越多,越来越能感觉到设计模式成为了我前进道路上的一个阻碍。所以从今天开始深入学习和总结经典的设计模...
阅读 1553·2023-04-26 02:29
阅读 3020·2021-10-11 10:58
阅读 2896·2021-10-08 10:16
阅读 3156·2021-09-24 09:47
阅读 1564·2019-08-29 16:56
阅读 2712·2019-08-29 11:03
阅读 1995·2019-08-26 13:35
阅读 3168·2019-08-26 13:34