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 相关文章推荐
原生javascript实现隔行换色
Jan 04 Javascript
jQuery用noConflict代替$的实现方法
Apr 12 jQuery
Vue利用路由钩子token过期后跳转到登录页的实例
Oct 26 Javascript
原生js实现简单的焦点图效果实例
Dec 14 Javascript
jQuery Validate插件ajax方式验证输入值的实例
Dec 21 jQuery
vue init失败简单解决方法(终极版)
Dec 22 Javascript
ES6之模版字符串的具体使用
May 17 Javascript
vue.draggable实现表格拖拽排序效果
Dec 01 Javascript
Vue 表情包输入组件的实现代码
Jan 21 Javascript
解决IOS端微信H5页面软键盘弹起后页面下方留白的问题
Jun 05 Javascript
使用js原生实现年份轮播选择效果实例
Jan 12 Javascript
JavaScript实现酷炫的鼠标拖尾特效
Feb 18 Javascript
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
eAccelerator的安装与使用详解
2013/06/13 PHP
phpcms配置列表页以及获得文章发布时间
2017/07/04 PHP
php生成静态页面并实现预览功能
2019/06/27 PHP
js 学习笔记(三)
2009/12/29 Javascript
Javascript 检测键盘按键信息及键码值对应介绍
2013/01/03 Javascript
js仿百度有啊通栏展示效果实现代码
2013/05/28 Javascript
JS实现控制表格内指定单元格内容对齐的方法
2015/03/30 Javascript
JS+CSS实现自动切换的网页滑动门菜单效果代码
2015/09/14 Javascript
AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值
2016/01/25 Javascript
基于JavaScript判断浏览器到底是关闭还是刷新(超准确)
2016/02/01 Javascript
jQuery中$.each()函数的用法引申实例
2016/05/12 Javascript
JS从一组数据中找到指定的单条数据的方法
2016/06/02 Javascript
knockoutjs动态加载外部的file作为component中的template数据源的实现方法
2016/09/01 Javascript
vue路由权限校验功能的实现代码
2020/06/07 Javascript
解决Ant Design Modal内嵌Form表单initialValue值不动态更新问题
2020/10/29 Javascript
[02:17]《辉夜杯》TRG战队巡礼
2015/10/26 DOTA
[19:54]夜魇凡尔赛茶话会 第一期02:看图识人
2021/03/11 DOTA
[32:30]夜魇凡尔赛茶话会 第一期01:谁是卧底
2021/03/11 DOTA
分享一个常用的Python模拟登陆类
2015/03/29 Python
Python安装第三方库及常见问题处理方法汇总
2016/09/13 Python
python嵌套字典比较值与取值的实现示例
2017/11/03 Python
Python使用pip安装报错:is not a supported wheel on this platform的解决方法
2018/01/23 Python
Python实现PS图像调整之对比度调整功能示例
2018/01/26 Python
python2.7+selenium2实现淘宝滑块自动认证功能
2018/02/24 Python
Python pyinotify模块实现对文档的实时监控功能方法
2018/10/13 Python
Python计算时间间隔(精确到微妙)的代码实例
2019/02/26 Python
python3实现单目标粒子群算法
2019/11/14 Python
使用Django实现把两个模型类的数据聚合在一起
2020/03/28 Python
基于html5 canvas实现漫天飞雪效果实例
2014/09/10 HTML / CSS
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
NFL欧洲商店(德国):NFL Europe Shop DE
2018/11/03 全球购物
党支部书记四风问题整改措施
2014/09/24 职场文书
2014年银行年终工作总结
2014/12/19 职场文书
jquery插件实现代码雨特效
2021/04/24 jQuery
Python中的datetime包与time包包和模块详情
2022/02/28 Python
OpenStack虚拟机快照和增量备份实现方法
2022/04/04 Servers