一. 认识策略模式

策略模式的定义:定义一系列的算法,将他们一个个封装起来,使他们直接可以相互替换。

策略模式是开发中常用的第二种设计模式,它在开发中非常常见,由两部分组成。第一部分是策略类,封装了许多具体的,相似的算法。第二部分是环境类,接受客户请求,随后将请求委托给策略类。说的通俗一点就是将相同算法的函数存放在一个包装里边,每个函数用相同的方式拿出来,就叫做策略模式。下面我们来通过代码实现深入了解一下。

二. 具体实现和思想

假如需要实现一个计算员工奖金的程序,效绩为 S 则发基本工资的4倍,A 则3倍,以此类推,那么我们正常实现该代码,是通过判断分支语句来实现。

1. 通过分支实现

        let bonus = function (performance, salary) {if(performance === "S") {return salary*4;}if(performance === "A") {return salary*3;}if(performance === "B") {return salary*2;}}

分析:该实现存在显著的缺点,如果随着效绩 的扩展,比如增加C,D,E, if 分支不断累加,使得代码越来越庞大。

因此我们使用策略模式来重构代码。

2.使用策略模式实现

        let performanceS = function () {};performanceS.prototype.calculate = function ( salary ) {return salary*4}let performanceA = function () {};performanceA.prototype.calculate = function ( salary ) {return salary*3}let performanceB = function () {};performanceB.prototype.calculate = function ( salary ) {return salary*2}let performanceC = function () {};performanceC.prototype.calculate = function ( salary ) {return salary*1}let 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("未设置绩效");}return this.strategy.calculate(this.salary);}let bonus = new Bonus();bonus.setSalary(10000);bonus.setStrategy(new performanceS());console.log(bonus.getBonus());

分析:重构后,我们将每种绩效算法单独成一个函数,需要计算某种绩效时只需要将其传入 getBonus 函数中,去掉了 if 分支,减少了性能消耗,并且使代码有了弹性,随时增加其他绩效,不需要更改原代码。

主要思想这段代码基于面向对象语言,引入了多态的概念,不适用于js。

3. JavaScript 版本的策略模式

        // js中函数也是对象,直接将 strategy 定义为函数let strategy = {"S": function ( salary ){return salary*4;},"A": function ( salary ) {return salary*3;},"B": function ( salary ) { return salary*2;}}let calculateBonus = function ( level, salary ) {return strategy[ level ]( salary );}console.log(calculateBonus('A', 20000)) // 6000

分析:js 的对象可以直接创建,将函数封装进去,这样一来,代码显得清晰简洁。代码的复用,弹性也随之变强。

以上就是 js 设计模式策略模式的主要思想和实现,他在应用中有两个主要的作用,一是策略模式实现晃动动画;二是实现表单验证,有能力有兴趣的小伙伴可以往下看。

三. 策略模式的实际运用

1. 使用策略模式实现缓存动画

        // 缓动算法let tween = {linear (t, b, c, d) {return c*t/d + b;},easeIn (t, b, c, d) {return c*(t /= d) *t + b;},strongEaseIn (t, b, c, d) {return c*(t /= d) *t *t *t *t + b;}}// 定义一个动画类,参数为要运动的 dom 节点let Animate = function ( dom ) {this.dom = dom;this.startTime = 0;this.startPos = 0;this.endPos = 0;this.propertyName = null;this.easing = null; // 缓动算法this.duration = null;}// 启动方法Animate.prototype.start = function (propertyName, endPos, duration, easing) {this.startTime =+ new Date;this.startPos = this.dom.getBoundingClientRect()[propertyName]; // dom 初始位置this.propertyName = propertyName;this.endPos = endPos;this.duration = duration;this.easing = tween[easing];let self = this;let timeId = setInterval(() => {if( self.step() === false){clearInterval(timeId);}}, 19);}// 实现小球每一帧要做的事情Animate.prototype.step = function () {let t =+ new Date;if(t>this.startTime + this.duration){this.update(this.endPos);return false;}let pos = this.easing(t - this.startTime, this.startPos, this.endPos - this.startPos, this.duration);this.update(pos);}Animate.prototype.update = function (pos) {this.dom.style[this.propertyName] = pos + 'px';}let test = function () {let div = document.getElementById('div');let animate = new Animate(div);animate.start('left', 500, 1000, 'strongEaseIn');// animate.start('top', 1500,  500, 'strongEaseIn');}test();

2. 使用策略模式进行表单验证

        let strategies = {isNonEmpty ( value, errorMsg) { // 判断是否为空if(value === '') {return errorMsg;}},minLength (value, length, errorMsg){if (value.length < length) {return errorMsg;}}}let dom = document.forms[0].acount;let validatarFunc = function () {let validator = new Validator();// 添加校验规则validator.add(dom, 'isNonEmpty', '用户名不能为空!');let errorMsg = validator.start();return errorMsg; // 返回校验结果}// 实现表单校验保存类let Validator = function () {this.cache = []; // 保存校验规则}Validator.prototype.add = function (dom, rule, errorMsg) {let ary = rule.split(':');this.cache.push( function(){let strategy = ary.shift();ary.unshift(dom.value);ary.push( errorMsg );return strategies[strategy].apply(dom, ary);})}Validator.prototype.start = function () {for(let i = 0, validatorFunc; validatorFunc = this.cache[i++];){let msg = validatorFunc();if( msg ) {return msg;}}}document.forms[0].addEventListener('submit', (e) =>{let errorMsg = validatarFunc();if(errorMsg){alert(errorMsg);e.preventDefault();}})

分析:第一个实现中是把缓动算法封装在一个对象中,调用他们时便于相互替换,也便于扩展。

第二个实现是将校验规则封装起来。

四. 总结

策略模式利用组合、委托、多态等技术思想,有效避免多重条件选择语句,将算法封装在 strategy 中,使他们易于切换、扩展。

js设计模式之策略模式相关推荐

  1. JS设计模式(策略模式)

    策略模式 概念 不同策略分开处理 避免出现大量if-else 或者 switch-case (JS 中未找到经典应用场景) 演示 青铜写法: 王者写法:(摆脱很多的if-else写法) 设计原则验证 ...

  2. JavaScript设计模式之策略模式(学习笔记)

    在网上搜索"为什么MVC不是一种设计模式呢?"其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composi ...

  3. Java设计模式之策略模式与状态模式

    一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...

  4. 换个姿势学设计模式:策略模式

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:公众号「闻人的技术博客」 前言 前段时间,接到一个 ...

  5. 研磨设计模式之 策略模式--转

    http://www.uml.org.cn/sjms/201009092.asp 研磨设计模式之 策略模式   2010-09-09 作者:云飞龙行 来源:云飞龙行的blog   先感谢众多朋友的支持 ...

  6. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  7. C++设计模式之策略模式(Strategy)

    Strategy策略模式 作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: 代码实现 #include <iostream& ...

  8. python策略模式包含角色_详解Python设计模式之策略模式

    虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中"不见了,或者简 ...

  9. 一篇博客读懂设计模式之-----策略模式

    设计模式之策略模式 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决:在有多种算法相似的情况下 ...

  10. 面向对象设计模式之策略模式

    面向对象设计模式之策略模式 1.策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 2.抽象鸭子类,鸭子飞行行为在此处类似于算法族 1 package ...

最新文章

  1. 【动态规划】炮兵阵地
  2. PowerShell在Exchange2010下快速创建动态通讯组
  3. leetcode102
  4. 软件史上最伟大的十大程序员(图文)
  5. 【渝粤题库】广东开放大学 婚姻家庭法 形成性考核
  6. 计算机视觉论文-2021-09-10
  7. 通过ResNet-50进行面部表情识别(易懂)
  8. 【无标题】全国矢量地图下载
  9. Jmeter随机常用变量
  10. 前端网站开发页面重定向的几种方法
  11. R绘图-KEGG功能注释组间差异分面条形图
  12. hexo博客中添加categories分类
  13. EOS 一周回顾(11.25-12.1)
  14. 雨林木风 Ghost XP SP2 精简版 Y2.0
  15. JDK源码分析---SortedMap
  16. K-Means(K均值聚类算法)
  17. Weblogic Server打补丁方法步骤
  18. Eclipse Virgo
  19. 微课竞赛系统的设计与实现所需工作条件_快速微课制作方法
  20. 百度自动驾驶小巴阿波龙Ⅱ落地广州;上汽通用五菱和江淮集团获汽车轻量化大奖 | 美通社头条...

热门文章

  1. Jetson nano 2G跑通Nvidia官方案例Jetson Inference
  2. sap的pod确认_VLPOD确认交付凭证
  3. java如何对一个表达式开根号_java实现开根号的运算
  4. 无密码如何破解PDF加密
  5. UI自动化报错Can not connect to the Service解决方案
  6. java 枚举 排序_基于枚举常量的Java排序
  7. 一文带你彻底了解电子灌封(灌胶)工艺技术
  8. iPhone手机微信下载的文档传输到win10系统桌面
  9. 怎样把IPv4转换成IPv6?
  10. (二三)计算机组成原理笔记整理之系统总线(总线判优方式,标准传输率,数据总线,地址总线与MDR,MAR的关系等)