JavaScript 程序设计模式小技巧——策略模式,快看快用!!!
前言
系列首发于公众号『非同质前端札记』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。
JavaScript 程序设计模式小技巧——策略模式,快看快用!!!
何为策略模式?
比如在业务逻辑或程序设计中比如要实现某个功能,有多种方案可供我们选择。比如要压缩一个文件,我们既可以选择 ZIP 算法,也可以选择 GZIP 算法。
这些算法灵活多样,可随意切换,而这种解决方案就是我们所要学习的策略模式。
定义或概念
策略模式:定义一系列的算法,将他们一个个封装,并使他们可相互替换。
策略模式的最佳实践
例子 1:奖金计算
题目:在很多公司的年终奖都是按照员工的工资基数和年底绩效情况来发放的,例如,绩效为 S 的人年终奖有 4 倍工资,A 的人年终奖有 3 倍,B 的人年终奖有 2 倍。要求我们写出一个程序来更快的计算员工的年终奖。(编写一个名为 calcBonus 方法来计算每个员工的奖金数额)
可能有些人一上来直接就在一个方法中进行很多 if...else 或 switch...case 判断, 然后通过这个方法进行计算。我们可以来试着写一下:
我想在我们每个人初学代码时肯定都写出过这样的代码。其实这段代码有显而易见的缺点:
calcBonus
函数逻辑太多
calcBonus 函数
缺乏弹性
,比如如果我们需要增加一个等级 C,那就必须要去修改 calcBonus 函数。这就违反了开放-封闭原则
。复用性差
。如果后续还要重用这个程序去计算奖金,我们只有去 C,V。此时,可能会想对 calcBonus 函数进行封装,如我们使用组合函数的形式,如下:
这样,我们将程序进行了进一步改善,但改善微乎其微,依旧没有解决最重要的问题,calcBonus 函数还是有可能会很庞大,并且也没有弹性。
那我们再将它进行一次改造,使用策略模式:
将其定义为一系列的算法,将他们每一个封装起来,将不变的部分和变化的部分隔开。
在这段程序中,
算法的使用方式是不变的,都是根据某个算法获取最后的奖金金额。而在每个算法的内部实现却是不同的,每一个等级对应着不同的计算规则
。而
在策略模式程序中:最少由两部分组成,一部分是一组策略类,在策略类中封装了具体的算法,并负责具体的计算过程。一部分是环境类 context,接受用户的请求,并将请求委托给某一个策略类。
如下:
其实,
策略模式的实现并不复杂,关键是如何从策略模式的实现背后,找到封装变化,委托和多态性这些思想的价值
。
例子 2:表单验证
题目:在 Web 开发中,表单校验是一个常见的话题,要求使用策略模式来完成表单验证。
比如:
用户名不能为空
密码长度不能少于 6 位
手机号码必须符合正确格式
让我们来实现一下吧:
这是我们常见的实现方式,它的缺点跟计算奖金一例类似:
submit 函数庞大,包含了很多 if...else 语句
submit 函数缺乏弹性,如果对其新加一些新的校验规则,如果我们把密码长度从 6 改到 8.那我们就必须要改动 submit 函数,否则无法实现该校验。这也是违反开放-封闭原则。
复用差,如果说我们程序中还有另一个表达需要验证,也是进行类似的校验,那我们可能会进行 C, V 操作。
使用策略模式来进行重构
使用策略模式重构后,我们后续仅需配置的方式来完成。
扩展题目:那如果想给用户名还想再添加一个规则,那如何完成呢?
添加规则方式如下:
实现:
策略模式的优缺点
优点:
利用组合,委托,多态等技术有效避免了多重条件语句
提供了对开封-封闭原则的完美支持
复用性较强,避免许多重复的 C,V 工作
缺点:
客户端要先了解所有的策略类,才能选择合适的策略类。
策略模式的角色
Context(环境类)
:持有一个 Strategy 类的引用,用一个 ConcreteStrategy 对象来配置Strategy(环境策略类)
:定义了所有支持的算法的公共接口,通常是以一个接口或抽象来实现。Context 使用这个接口来调用其 ConcreteStrategy 定义的算法。ConcreteStrategy(具体策略类)
:以 Strategy 接口实现某种算法
比如以上的例子算法:
策略模式的应用场景
想使用对象中各种不同算法变体来在运行时切换算法时
拥有很多在执行某些行为时有着不同的规则时
Tip: 文章部分内容参考于曾探
大佬的《JavaScript 设计模式与开发实践》。文章仅做个人学习总结和知识汇总
特殊字符描述:
问题标注
Q:(question)
答案标注
R:(result)
注意事项标准:
A:(attention matters)
详情描述标注:
D:(detail info)
总结标注:
S:(summary)
分析标注:
Ana:(analysis)
提示标注:
T:(tips)
往期推荐:
最后:
版权声明: 本文为 InfoQ 作者【控心つcrazy】的原创文章。
原文链接:【http://xie.infoq.cn/article/fb0ead4ea3fb69db102277bd9】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论