JavaScript 设计模式:职责链模式原理与实战
本文深入解析 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 程序设计有所帮助。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
