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 相关文章推荐
10个基于浏览器的JavaScript调试工具分享
Feb 07 Javascript
让js弹出窗口居前显示的实现方法
Jul 10 Javascript
JS获取网页属性包括宽、高等等
Apr 03 Javascript
使用JS获取当前地理位置方法汇总
Dec 18 Javascript
JS动态加载当前时间的方法
Feb 09 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
Mar 04 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
Dec 15 Javascript
checkbox:click事件触发span元素内容改变的方法
Sep 11 Javascript
详解RequireJs官方使用教程
Oct 31 Javascript
jQuery轮播图实例详解
Aug 15 jQuery
详解JVM系列之内存模型
Jun 10 Javascript
Vue2项目中对百度地图的封装使用详解
Jun 16 Vue.js
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
PHP 八种基本的数据类型小结
2011/06/01 PHP
php实现通用的信用卡验证类
2015/03/24 PHP
PHP mysqli_free_result()与mysqli_fetch_array()函数详解
2016/09/21 PHP
EarthLiveSharp中cloudinary的CDN图片缓存自动清理python脚本
2017/04/04 PHP
fix-ie5.js扩展在IE5下不能使用的几个方法
2007/08/20 Javascript
AJAX的跨域与JSONP(为文章自动添加短址的功能)
2010/01/17 Javascript
ScrollDown的基本操作示例
2013/06/09 Javascript
常见表单重复提交问题整理及解决方法
2013/11/13 Javascript
通过js获取上传的图片信息(临时保存路径,名称,大小)然后通过ajax传递给后端的方法
2015/10/01 Javascript
jQuery事件绑定用法详解(附bind和live的区别)
2016/01/19 Javascript
JavaScript File分段上传
2016/03/10 Javascript
Javascript中的迭代、归并方法详解
2016/06/14 Javascript
学习Javascript闭包(Closure)知识
2016/08/07 Javascript
Kendo Grid editing 自定义验证报错提示的解决方法
2016/11/18 Javascript
解决v-for中使用v-if或者v-bind:class失效的问题
2018/09/25 Javascript
原生JS实现的放大镜特效示例【测试可用】
2018/12/08 Javascript
jQuery zTree插件快速实现目录树
2019/08/16 jQuery
JavaScript setTimeout()基本用法有哪些
2020/11/04 Javascript
[33:23]VG vs Pain 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
[02:17]快乐加倍!DOTA2食人魔魔法师至宝+迎霜节活动上线
2019/12/22 DOTA
python创建关联数组(字典)的方法
2015/05/04 Python
Python实现钉钉发送报警消息的方法
2019/02/20 Python
关于pytorch中网络loss传播和参数更新的理解
2019/08/20 Python
对Python获取屏幕截图的4种方法详解
2019/08/27 Python
浅谈Python type的使用
2019/11/19 Python
tensorflow tf.train.batch之数据批量读取方式
2020/01/20 Python
python读取图片的几种方式及图像宽和高的存储顺序
2020/02/11 Python
python利用platform模块获取系统信息
2020/10/09 Python
Python类class参数self原理解析
2020/11/19 Python
JINS眼镜官方网站:日本最大的眼镜邮购
2016/10/14 全球购物
LN-CC美国:伦敦时尚生活的缩影
2019/02/19 全球购物
土木工程实习生自我鉴定
2013/09/19 职场文书
群众路线剖析材料(四风问题)
2014/10/08 职场文书
高校群众路线教育实践活动剖析材料
2014/10/10 职场文书
违纪检讨书
2015/01/27 职场文书
个人工作保证书
2015/02/28 职场文书