概念
职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系
职责链模式通常涉及两个核心角色:处理者(Handler)和客户端(Client)
处理者(Handler)
定义了一个处理请求的接口,并维护了一个后继处理者的引用
处理者可以决定是否处理请求,或者将请求传递给后继处理者
客户端(Client)
创建处理者对象,并将请求发送给处理者链的第一个处理者
客户端通常不需要知道处理者链的具体结构,只需要将请求发送给第一个处理者即可
职责链模式的核心思想是将请求发送者和接收者解耦,使得多个对象都有机会处理请求,并且可以灵活地调整处理者链的结构
这种模式的优点在于,可以降低请求发送者和接收者之间的耦合度,提高系统的灵活性和可扩展性
职责链模式适用于以下情况:
- 当有多个对象可以处理同一个请求,并且希望将请求发送者和接收者解耦时,可以使用职责链模式
- 当希望动态地调整处理者链的结构,并且希望在运行时决定请求的处理者时,职责链模式也是一个很好的选择
举个简单的例子,考虑一个请假审批系统
请假申请可以被多个领导依次审批,而每个领导都有不同的审批权限
职责链模式可以将每个领导视为一个处理者对象,并将请假申请发送给处理者链的第一个处理者
如果第一个处理者无法处理请求,则将请求传递给下一个处理者,直到找到能够处理请求的处理者为止
这样,可以实现请求发送者和接收者的解耦,同时也提供了一种灵活的方式来处理请求
实现条件
多个对象处理同一请求
职责链模式适用于多个对象处理同一请求的情况,请求会按照一定的顺序经过一系列的处理者,直到找到合适的处理者处理请求为止
请求发送者不需要明确知道接收
职责链模式适用于请求发送者不需要明确知道接收者是谁的情况,请求发送者只需要将请求发送给第一个处理者,由处理者之间相互传递请求,直到找到合适的处理者
请求可以被任意处理者处理
职责链模式适用于请求可以被任意处理者处理的情况,处理者之间没有严格的顺序要求,可以根据具体情况自由选择处理请求的方式
需要动态添加或者删除处理者
职责链模式适用于需要动态添加或者删除处理者的情况,处理者之间的关系是动态变化的,可以根据需要灵活地调整处理者的顺序和数量
优点
降低耦合度
职责链模式将请求发送者和接收者解耦,请求发送者不需要知道具体的接收者是谁,接收者也不需要知道请求的发送者是谁,从而降低了对象之间的耦合度
增强灵活性
职责链模式允许请求沿着一条链传递,每个处理者都有机会处理请求或者将请求传递给下一个处理者,从而增强了系统的灵活性和可扩展性
简化对象的相互连接
职责链模式可以简化对象之间的相互连接,每个处理者只需要保存对下一个处理者的引用即可,无需了解整个处理链的结构,降低了系统的复杂度
增强了请求的处理过程
职责链模式将请求的处理过程分解成多个处理者来共同完成,每个处理者只负责自己能够处理的部分,使得请求的处理过程更加清晰和可控
动态添加或者删除处理者职
责链模式允许动态地添加或者删除处理者,处理者之间的关系是动态变化的,可以根据需要灵活地调整处理者的顺序和数量
缺点
请求可能未被处理
如果请求没有合适的处理者来处理,可能会导致请求未被处理,需要额外的机制来处理这种情况,例如设置一个默认处理者
性能问题
职责链模式可能会导致性能问题,特别是处理链比较长或者请求频繁的情况下,可能会造成请求的传递和处理延迟
调试困难
由于请求的处理过程被分解到多个处理者中,可能会导致调试困难,难以确定请求的处理流程和具体是哪个处理者处理了请求
可能导致循环引用
如果处理链中存在循环引用的情况,可能会导致请求无法正常处理,甚至造成系统崩溃,需要谨慎设计处理链的结构
实现方式
处理者基类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
class Processor {
constructor(name, authorityLevel) { if (new.target === Processor) { throw new Error("不能实例化抽象类Processor") } this.name = name this.authorityLevel = authorityLevel this.nextProcessor = null }
setNextProcessor(nextProcessor) { if (!(nextProcessor instanceof Processor)) { throw new Error("下一个审批者必须是Processor的实例") } this.nextProcessor = nextProcessor }
processRequest(request) { throw new Error("必须实现processRequest方法") } }
export default Processor
|
子类基类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| import Processor from '../ChainOfResponsibilityPattern'
class TeamLeader extends Processor {
constructor() { super("团队领导", 2) }
processRequest(request) { if (request.leaveDays <= this.authorityLevel) { console.log(`${this.name}审批了${request.leaveDays}天的请假。`) } else if (this.nextProcessor) { console.log(`${this.name}无法处理,请转交给${this.nextProcessor.name}`) this.nextProcessor.processRequest(request) } else { console.log(`无法处理,请假天数过长。`) } } }
export default TeamLeader
import Processor from '../ChainOfResponsibilityPattern'
class DepartmentManager extends Processor {
constructor() { super("部门经理", 5) }
processRequest(request) { if (request.leaveDays <= this.authorityLevel) { console.log(`${this.name}审批了${request.leaveDays}天的请假。`) } else if (this.nextProcessor) { console.log(`${this.name}无法处理,请转交给${this.nextProcessor.name}`) this.nextProcessor.processRequest(request) } else { console.log(`无法处理,请假天数过长。`) } } }
export default DepartmentManager
import Processor from '../ChainOfResponsibilityPattern'
class HRManager extends Processor {
constructor() { super("人力资源经理", 10) }
processRequest(request) { if (request.leaveDays <= this.authorityLevel) { console.log(`${this.name}审批了${request.leaveDays}天的请假。`) } else if (this.nextProcessor) { console.log(`${this.name}无法处理,请转交给${this.nextProcessor.name}`) this.nextProcessor.processRequest(request) } else { console.log(`无法处理,请假天数过长。`) } } }
export default HRManager
class LeaveRequest { constructor(leaveDays) { this.leaveDays = leaveDays; } }
export default LeaveRequest;
|
怎么使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
import TeamLeader from '../SubClass/TeamLeader' import DepartmentManager from '../SubClass/DepartmentManager' import HRManager from '../SubClass/HRManager' import LeaveRequest from '../SubClass/LeaveRequest'
const teamLeader = new TeamLeader() const departmentManager = new DepartmentManager() const hrManager = new HRManager()
teamLeader.setNextProcessor(departmentManager) departmentManager.setNextProcessor(hrManager)
const request1 = new LeaveRequest(1) const request3 = new LeaveRequest(3) const request7 = new LeaveRequest(7) const request12 = new LeaveRequest(12)
teamLeader.processRequest(request1) teamLeader.processRequest(request3) teamLeader.processRequest(request7) teamLeader.processRequest(request12)
|
场景
电子商务订单处理系统
假设一个电子商务平台,订单的处理包括库存检查、支付验证、地址验证、配送等多个环节
每个环节都有不同的处理者,可以使用职责链模式来构建订单处理流程
订单首先经过库存检查处理者,如果库存充足,则传递给支付验证处理者,依次类推,直到订单被完全处理
工作流引擎
工作流引擎是一种用于管理和执行工作流程的系统
在工作流引擎中,每个工作流程包含多个步骤或任务,每个步骤都有对应的处理者
职责链模式可以用来管理工作流程中的步骤和处理者,以实现任务的自动化处理
网络安全防护系统
在网络安全防护系统中,通常会对网络流量进行多层次的检测和过滤,包括入侵检测、恶意软件检测、数据包过滤等
每个检测和过滤功能可以作为一个处理者,通过职责链模式将它们串联起来,以便逐层检测和过滤网络流量
工程质量检查系统
在软件开发中,经常需要进行代码审查和质量检查,以确保代码符合规范和质量标准
可以使用职责链模式来构建质量检查系统,其中每个质量检查功能(如代码格式检查、代码风格检查、代码性能检查等)作为一个处理者,根据需要逐个应用于待检查的代码
文件处理系统
在文件处理系统中,可能需要对不同类型的文件进行处理,如文本文件、图像文件、音频文件等
每种类型的文件都需要不同的处理方式,可以使用职责链模式来管理文件处理流程,使得每个文件根据其类型被传递给相应的处理者进行处理
源代码