设计模式——职责链模式
设计模式——职责链模式
参考尚硅谷宋红康老师的图解设计模式
场景描述
学校采购一批 OA 系统时,需要根据采购金额决定审批人:
例如:
5000 元,主任审批
6000 元,校长审批
8000 元,教育部审批
传统解决方案
传统方案中,采购金额与审批人之间存在硬编码关系,通常使用 if-else
或 switch
来判断金额,并决定审批人。
这种方式有以下问题:
- 代码不灵活:如果金额范围改变,客户端需要进行大规模修改。
- 强耦合:客户端需要了解所有审批级别和金额区间,导致系统的代码维护困难。
职责链模式通过将请求的处理责任沿着一个链条传递来解决上述问题。每个处理者持有对下一个处理者的引用,如果当前处理者无法处理请求,则将请求传递给下一个处理者,直到有处理者能够处理请求。
职责链模式的组成部分
- Handler(处理者):定义一个处理请求的接口,并持有对下一个处理者的引用。
- ConcreteHandler(具体处理者):实现了具体的请求处理逻辑,如果该处理者无法处理请求,则将请求传递给下一个处理者。
- Request(请求):表示一个具体的请求,通常包含多个属性,如请求的金额、类型等。
示例图
职责链模式
具体实现
Approver
(抽象处理者)
package top.miqiu.designPatternDemo.responsibilityChan;
import lombok.Data;
@Data
public abstract class Approver {
Approver approver; // 下一个处理者
String name;
public Approver(String name){
this.name = name;
}
// 处理审批请求的抽象方法,具体实现由子类完成
public abstract void processRequest(Purchaserequest purchaserequest);
}
Client
(客户端)
package top.miqiu.designPatternDemo.responsibilityChan;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.CollegeAprover;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.DepartmentApprover;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.SchoolMasterApprover;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.ViceSchoolMasterApprover;
public class Client {
public static void main(String[] args) {
// 创建采购请求
Purchaserequest purchaserequest = new Purchaserequest(1, 1000, 1);
// 创建相关的审批人
DepartmentApprover departmentApprover = new DepartmentApprover("张主任");
CollegeAprover collegeAprover = new CollegeAprover("李院长");
ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校长");
SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("杨校长");
// 构建审批链:从部门审批到校长审批
departmentApprover.setApprover(collegeAprover);
collegeAprover.setApprover(viceSchoolMasterApprover);
viceSchoolMasterApprover.setApprover(schoolMasterApprover);
// 发起请求并处理
schoolMasterApprover.processRequest(purchaserequest);
}
}
Purchaserequest
(请求类)
package top.miqiu.designPatternDemo.responsibilityChan;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Purchaserequest {
private int type = 0; // 请求类型
private float price = 0.0f; // 请求金额
private int id = 0; // 请求ID
}
SchoolMasterApprover
(具体处理者)
package top.miqiu.designPatternDemo.responsibilityChan.processerImpl;
import top.miqiu.designPatternDemo.responsibilityChan.Approver;
import top.miqiu.designPatternDemo.responsibilityChan.Purchaserequest;
public class SchoolMasterApprover extends Approver {
public SchoolMasterApprover(String name) {
super(name);
}
@Override
public void processRequest(Purchaserequest purchaserequest) {
// 校长审批金额大于 7000 的请求
if (purchaserequest.getPrice() > 7000) {
System.out.println("请求ID:" + purchaserequest.getId() + " 由 " + this.getName() + " 处理");
} else {
// 转交给下一个处理者
this.getApprover().processRequest(purchaserequest);
}
}
}
在源码中的运用
在 Spring MVC 中,请求的处理遵循类似的职责链模式。具体而言,HandlerExecutionChain
的职责是将请求分配给链路上的处理器。Spring MVC 中有一个拦截器链,负责请求的预处理和后处理。
HandlerExecutionChain
内部维护了一个 HandlerExecutionInterceptor
的集合,拦截器会在请求处理前后分别执行 preHandle
和 postHandle
方法,从而形成职责链的模式。每个拦截器执行时,都可以判断是否继续处理请求,或者终止链的执行。
注意事项与细节
好处:
- 解耦请求和处理逻辑:请求和处理过程解耦,使得对象不需要知道链的结构,便于扩展和维护。
- 灵活性:可以通过动态添加处理者来灵活调整审批流程。
缺点:
- 性能开销:如果链条过长,可能会对性能产生一定影响,需要考虑最大节点数的控制。
- 调试困难:链式结构的调试较为复杂,可能需要追踪多个处理者的执行流程。
总结
职责链模式非常适合用于多个对象可以处理同一请求的场景。它使得系统可以灵活地调整请求的处理顺序和流程,而不需要修改客户端代码,从而降低了系统的耦合度和维护成本。