JavaScript 设计模式:职责链模式原理与实战

作者:拾光时间:2026-10-23 17:32:12浏览:110

本文深入解析 JavaScript 中的职责链模式,通过绘制不同大小圆形的代码示例,对比传统 if-else 逻辑与职责链实现的差异。详细阐述纯与不纯职责链的区别,分析其在降低耦合、满足开闭原则方面的优势,以及可能导致的性能问题和死循环风险,帮助开发者掌握该模式在复杂请求处理中的应用。

本文通过具体实例解析 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.jb51.net/code/HtmlJsRun 测试上述代码的运行效果。

更多关于 JavaScript 相关内容感兴趣的读者可查看本站专题:《javascript 面向对象入门教程》、《JavaScript 错误与调试技巧总结》、《JavaScript 数据结构与算法技巧总结》、《JavaScript 遍历算法与技巧总结》及《JavaScript 数学运算用法总结》。

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

作者最新文章