javascript设计模式 ? 职责链模式原理与用法实例分析


Posted in Javascript onApril 16, 2020

本文实例讲述了javascript设计模式 ? 职责链模式原理与用法。分享给大家供大家参考,具体如下:

介绍:很多情况下,在一个软件系统中可以处理某个请求的对象不止一个。例如一个网络请求过来,需要有对象去解析request Body,需要有对象去解析请求头,还需要有对象去对执行对应controller。请求一层层传递,让每一个对象都基于请求完成自己的任务,然后将请求传递给下一个处理程序。是不是感觉有点中间件的感觉。

定义:职责链就是避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求。将这些对象连成一条链,并沿着链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。

场景:我们继续画圆,我们准备了两组示例:

示例:

var Circle = function(){
  this.radius = 0;
 
  this.drawByRadius = function(radius){
    if(radius < 5){
      this.drawVerySmalCircle();
    }else if(radius < 10){
      this.drawSmalCircle();
    }else if(radius < 15){
      this.drawMediumCircle();
    }else if(radius < 20){
      this.drawBigCircle();
    }else{
      this.drawVeryBigCircle();
    }
  }
 
  this.drawVerySmalCircle = function(){
    console.log('画一个超小的圆( 5以下 )');
  }
  this.drawSmalCircle = function(){
    console.log('画一个小圆( 5-10 )');
  }
  this.drawMediumCircle = function(){
    console.log('画一个中圆 ( 10-15 )');
  }
  this.drawBigCircle = function(){
    console.log('画一个大圆 ( 15-20 )');
  }
  this.drawVeryBigCircle = function(){
    console.log('画一个超大的圆 ( 20以上 )');
  }
}
 
var circle = new Circle();
circle.drawByRadius(30);
//画一个超大的圆 ( 20以上 )

观察上面的代码,这是很常见的逻辑,通过参数来决定执行哪个方法。首先drawByRadius方法职责过重,其次这样的方式在修改,新增时需要修改源代码,不符合开关原则。

我们使用职责链模式重写下:

var drawSmalCircle = function(min,max){
  this.max = max;
  this.min = min;
  this.nextCircle;
  this.setNextDraw = function(circle){
    this.nextCircle = circle;
  }
  this.draw = function(radius){
    console.log('执行:drawSmalCircle');
    if(this.min < radius && radius < this.max){
      console.log('画一个小圆( 10以下 )');
    }
    if(this.nextCircle){
      this.nextCircle.draw(radius)
    }
  }
}
 
var drawMediumCircle = function(min,max){
  this.max = max;
  this.min = min;
  this.nextCircle;
  this.setNextDraw = function(circle){
    this.nextCircle = circle;
  }
  this.draw = function(radius){
    console.log('执行:drawMediumCircle');
    if(this.min < radius && radius < this.max){
      console.log('画一个中圆 ( 10-20 )');
    }
    if(this.nextCircle){
      this.nextCircle.draw(radius)
    }
  }
}
 
var drawBigCircle = function(min,max){
  this.max = max;
  this.min = min;
  this.nextCircle;
  this.setNextDraw = function(circle){
    this.nextCircle = circle;
  }
  this.draw = function(radius){
    console.log('执行:drawBigCircle');
    if(this.min < radius && radius < this.max){
      console.log('画一个大圆 ( 20以上 )');
    }
    if(this.nextCircle){
      this.nextCircle.draw(radius)
    }
  }
}
 
function initChain(){
  var smalCircle = new drawSmalCircle(0,10);
  var mediumCircle = new drawMediumCircle(10,20);
  var bigCircle = new drawBigCircle(20,100);
 
  smalCircle.setNextDraw(mediumCircle);
  mediumCircle.setNextDraw(bigCircle);
  return smalCircle;
}
 
var circle = initChain();
circle.draw(30)
// 执行:drawSmalCircle
// 执行:drawMediumCircle
// 执行:drawBigCircle
// 画一个大圆 ( 20以上 
circle.draw(15)
// 执行:drawSmalCircle
// 执行:drawMediumCircle
// 画一个中圆 ( 10-20 )
// 执行:drawBigCircle
circle.draw(5)
// 执行:drawSmalCircle
// 画一个小圆( 10以下 )
// 执行:drawMediumCircle
// 执行:drawBigCircle

以上就是职责链模式的实例代码,drawSmalCircle,drawMediumCircle,drawBigCircle称为处理者类,处理者类保存了下一级对象的引用,

当我每执行一次draw时,程序会挨个执行职责链上的每一个方法。

职责链模式分为纯职责链和不纯职责链,纯的职责链在处理请求时,只能选择全部处理不传递或者全部传递不处理。我们这里的例子就是不纯职责链。它允许处理完成后继续向后传递。

职责链模式总结:

优点:
* 降低耦合,互相都不清楚执行顺序以及执行处理的类。
* 请求对象仅需维持一个指向其后继者的引用,简化了对象的相互连接。
* 新增修改职责链结构方便,满足开关原则。

缺点:
* 由于没有明确接受者,可能职责链走到最后都没有被正确处理。
* 职责链较长时会导致系统性能受影响。
* 建链不当,会造成循环调用,导致系统陷入死循环。

适用场景:
* 多个对象处理同一请求
* 动态创建执行顺序,流程

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
jQuery实现类似滑动门切换效果的层切换
Sep 23 Javascript
jquery自动切换tabs选项卡的具体实现
Dec 24 Javascript
js showModalDialog弹出窗口实例详解
Jan 07 Javascript
JavaScript数值转换的三种方式总结
Jul 31 Javascript
AngularJS 中的事件详解
Jul 28 Javascript
JavaScript常用代码书写规范的超全面总结
Sep 11 Javascript
jQuery实现输入框邮箱内容自动补全与上下翻动显示效果【附demo源码下载】
Sep 20 Javascript
在使用JSON格式处理数据时应该注意的问题小结
May 20 Javascript
深究AngularJS之ui-router详解
Jun 13 Javascript
JS实现非首屏图片延迟加载的示例
Jan 06 Javascript
详解vue 单页应用(spa)前端路由实现原理
Apr 04 Javascript
jQuery发请求传输中文参数乱码问题的解决方案
May 22 jQuery
vue下canvas裁剪图片实例讲解
Apr 16 #Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
Apr 16 #Javascript
js String.prototype.trim字符去前后空格的扩展
Aug 23 #Javascript
Vue Object 的变化侦测实现代码
Apr 15 #Javascript
Vue项目vscode 安装eslint插件的方法(代码自动修复)
Apr 15 #Javascript
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
Apr 15 #Javascript
javascript设计模式 ? 享元模式原理与用法实例分析
Apr 15 #Javascript
You might like
如何提高MYSQL数据库的查询统计速度 select 索引应用
2007/04/11 PHP
PHPnow安装服务[apache_pn]失败的问题的解决方法
2010/09/10 PHP
初学PHP的朋友 经常问的一些问题。不断更新
2011/08/11 PHP
php学习笔记之字符串常见操作总结
2019/07/16 PHP
收藏Javascript中常用的55个经典技巧
2007/08/12 Javascript
传智播客学习之java 反射
2009/11/22 Javascript
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
Jquery之Ajax运用 学习运用篇
2011/09/26 Javascript
深入理解JavaScript 闭包究竟是什么
2013/04/12 Javascript
JavaScript避免内存泄露及内存管理技巧
2014/09/05 Javascript
javascript 面向对象封装与继承
2014/11/27 Javascript
javascript实现密码强度显示
2015/03/18 Javascript
jQuery实现自动切换播放的经典滑动门效果
2015/09/12 Javascript
vue.js将unix时间戳转换为自定义时间格式
2017/01/03 Javascript
利用prop-types第三方库对组件的props中的变量进行类型检测
2017/05/02 Javascript
vue解决一个方法同时发送多个请求的问题
2018/09/25 Javascript
浅谈小程序globalData的那些事儿
2019/11/01 Javascript
Vue快速实现通用表单验证的示例代码
2020/01/09 Javascript
ant-design-vue 快速避坑指南(推荐)
2020/01/21 Javascript
JS端基于download.js实现图片、视频时直接下载而不是打开预览
2020/05/09 Javascript
[14:03]2017DOTA2亚洲邀请赛开幕式:12神兵演绎水墨中华
2017/04/01 DOTA
Python字典简介以及用法详解
2016/11/15 Python
深入浅析Python 函数注解与匿名函数
2020/02/24 Python
python3实现往mysql中插入datetime类型的数据
2020/03/02 Python
带有css3动画效果的兼容多浏览器简单导航条示例
2014/01/26 HTML / CSS
英格兰橄榄球商店:England Rugby Store
2016/12/17 全球购物
美国在线纱线商店:Darn Good Yarn
2019/03/20 全球购物
什么是反射?如何实现反射?
2016/07/25 面试题
如何防止同一个帐户被多人同时登录
2013/08/01 面试题
货代行业个人求职简历的自我评价
2013/10/22 职场文书
测试工程师程序员求职信范文
2014/02/20 职场文书
冬季安全检查方案
2014/05/23 职场文书
小学教师师德整改措施
2014/09/29 职场文书
2014年学生资助工作总结
2014/12/18 职场文书
工作收入证明模板
2015/06/12 职场文书
Redis高级数据类型Hyperloglog、Bitmap的使用
2021/05/24 Redis