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 原型模式实现OOP的再研究
Apr 09 Javascript
jQuery 渐变下拉菜单
Dec 15 Javascript
JS取得绝对路径的实现代码
Jan 16 Javascript
mui 打开新窗口的方式总结及注意事项
Aug 20 Javascript
vue中页面跳转拦截器的实现方法
Aug 23 Javascript
解决JavaScript中0.1+0.2不等于0.3问题
Oct 23 Javascript
微信小程序实现的自定义分享功能示例
Feb 12 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
May 05 Javascript
微信小程序日历插件代码实例
Dec 04 Javascript
js点击事件的执行过程实例分析【冒泡与捕获】
Apr 11 Javascript
Vue ElementUI实现:限制输入框只能输入正整数的问题
Jul 31 Javascript
vue自动添加浏览器兼容前后缀操作
Aug 13 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中Object对象的笔记分享
2011/06/28 PHP
php判断GIF图片是否为动画的方法
2020/09/04 PHP
常用的php图片处理类(水印、等比缩放、固定高宽)分享
2015/06/19 PHP
PHP通过反射动态加载第三方类和获得类源码的实例
2015/11/27 PHP
php 流程控制switch的简单实例
2016/06/07 PHP
PHP 进度条函数的简单实例
2017/09/19 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
PHP实现百度人脸识别
2019/05/06 PHP
Laravel 自定命令以及生成文件的例子
2019/10/23 PHP
JS 控制非法字符的输入代码
2009/12/04 Javascript
JS异常处理的一个想法(sofish)
2013/03/14 Javascript
JS 对象属性相关(检查属性、枚举属性等)
2015/04/05 Javascript
基于javascript实现随机颜色变化效果
2016/01/14 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
Angular2.js实现表单验证详解
2017/06/23 Javascript
关于express与koa的使用对比详解
2018/01/25 Javascript
vue实现的多页面项目如何优化打包的步骤详解
2020/07/19 Javascript
利用Python为iOS10生成图标和截屏
2016/09/24 Python
利用python实现简单的循环购物车功能示例代码
2017/07/05 Python
Python数据结构与算法之完全树与最小堆实例
2017/12/13 Python
python+pandas生成指定日期和重采样的方法
2018/04/11 Python
Python实现的简单排列组合算法示例
2018/07/04 Python
python使用rpc框架gRPC的方法
2018/08/24 Python
Python3安装Pillow与PIL的方法
2019/04/03 Python
python下载库的步骤方法
2019/10/12 Python
python 决策树算法的实现
2020/10/09 Python
this关键字的含义
2015/04/08 面试题
什么是Linux虚拟文件系统VFS
2012/01/31 面试题
结婚典礼证婚词
2014/01/11 职场文书
美术教师个人总结
2015/02/06 职场文书
离婚律师函范本
2015/05/27 职场文书
文艺演出主持词
2015/07/01 职场文书
幼儿园语言教学反思
2016/02/23 职场文书
学校2016年圣诞节活动总结
2016/03/31 职场文书
Nginx动静分离配置实现与说明
2022/04/07 Servers
微软发布Windows 11今年最大更新22H2(附 ISO 镜像官方下载)
2022/09/23 数码科技