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图像处理思路及实现代码
Dec 25 Javascript
jquery实现的一个导航滚动效果具体代码
May 27 Javascript
使用jquery动态加载js文件的方法
Dec 24 Javascript
JavaScript操作Oracle数据库示例
Mar 06 Javascript
详解JavaScript的AngularJS框架中的作用域与数据绑定
Mar 04 Javascript
vue页面切换到滚动页面显示顶部的实例
Mar 13 Javascript
在HTML文档中嵌入JavaScript的四种方法
May 07 Javascript
vue 项目打包通过命令修改 vue-router 模式 修改 API 接口前缀
Jun 13 Javascript
详解小程序输入框闪烁及重影BUG解决方案
Aug 31 Javascript
vue 之 css module的使用方法
Dec 04 Javascript
Vue中遍历数组的新方法实例详解
Jul 21 Javascript
Elementui表格组件+sortablejs实现行拖拽排序的示例代码
Aug 28 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
将PHP作为Shell脚本语言使用
2006/10/09 PHP
php网站判断用户是否是手机访问的方法
2013/11/01 PHP
详解PHP字符串替换str_replace()函数四种用法
2017/10/13 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
基于ThinkPHP5框架使用QueryList爬取并存入mysql数据库操作示例
2019/05/25 PHP
PHP使用PDO创建MySQL数据库、表及插入多条数据操作示例
2019/05/30 PHP
jQuery瀑布流插件Wookmark使用实例
2014/04/02 Javascript
ExtJS4 表格的嵌套 rowExpander应用
2014/05/02 Javascript
Javascript 数组排序详解
2014/10/22 Javascript
JavaScript中解析JSON数据的三种方法
2015/07/03 Javascript
jQuery遮罩层效果实例分析
2016/01/14 Javascript
javascript拖拽应用实例(二)
2016/03/25 Javascript
jquery实现网页定位导航
2016/08/23 Javascript
JS实现的自动打字效果示例
2017/03/10 Javascript
js使用i18n实现页面国际化的方法
2017/05/09 Javascript
收藏AngularJS中最重要的核心功能
2017/07/09 Javascript
Angularjs的启动过程分析
2017/07/18 Javascript
原生js的ajax和解决跨域的jsonp(实例讲解)
2017/10/16 Javascript
nodejs微信扫码支付功能实现
2018/02/17 NodeJs
微信小程序websocket聊天室的实现示例代码
2019/02/12 Javascript
Vue拖拽组件列表实现动态页面配置功能
2019/06/17 Javascript
微信小程序使用自定义组件导航实现当前页面高亮
2020/01/02 Javascript
Vue-Ant Design Vue-普通及自定义校验实例
2020/10/24 Javascript
Vue 实现拨打电话操作
2020/11/16 Javascript
Django CSRF跨站请求伪造防护过程解析
2019/07/31 Python
Python自动采集微信联系人的实现示例
2020/02/28 Python
Ticketmaster德国票务网站:购买音乐会和体育等门票
2016/11/14 全球购物
瑞典快乐袜子:Happy Socks
2018/02/16 全球购物
俄罗斯设计师家具购物网站:The Furnish
2019/12/01 全球购物
仓库主管的岗位职责
2013/12/04 职场文书
优秀教师的感人事迹
2014/02/04 职场文书
供用电专业求职信
2014/07/07 职场文书
社区个人对照检查材料(群众路线)
2014/09/26 职场文书
使用Html+Css实现简易导航栏功能(导航栏遇到鼠标切换背景颜色)
2021/04/07 HTML / CSS
golang goroutine顺序输出方式
2021/04/29 Golang
redis中lua脚本使用教程
2021/11/01 Redis