一、什么是责任链模式?
责任链模式(Chain of Responsibility Pattern) 是一种行为型设计模式,它让多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,沿着这条链传递请求,直到有对象处理它为止。一般用在如下的场景
- 多个对象可以处理同一个请求,但具体由哪个处理方未确定;
- 系统需动态指定处理者;
- 想在运行时灵活地添加新的处理节点;
可能比较抽象,今天本篇就以例子的方式,让你快速理解到这些文字描述。
二、责任链例子
小张想请假,走公司流程:
小张 → 班组长 → 主管 → 部门经理 → 总经理
- 小张请 1 天假,班组长就能批;
- 请 3 天假,需要主管审批;
- 请 7 天,得上总经理签字。
这就是责任链流程。谁能处理就在哪停下,不能处理就往上交。
三、UML结构图
在这里插入图片描述
Handler
定义处理请求的接口;- 每个
Leader
具体处理不同级别的请求; - 请求不能处理时,传给下一个节点。
四、代码实现
抽象处理者
构建一个抽象的 Handler类。
// 抽象类,定义处理逻辑和下一个节点
public abstract class Handler {protected Handler next;public void setNext(Handler next) {this.next = next;}// 处理请求的方法public abstract void handleRequest(int leaveDays);
}
具体处理者
具体处理审批十各级审批人。
// 班组长处理1天以内的请假
public class TeamLeader extends Handler {@Overridepublic void handleRequest(int leaveDays) {if (leaveDays <= 1) {System.out.println("班组长批准了" + leaveDays + "天的请假");} else if (next != null) {System.out.println("班组长无权处理,转交主管");next.handleRequest(leaveDays);}}
}
// 主管处理3天以内的请假
public class Supervisor extends Handler {@Overridepublic void handleRequest(int leaveDays) {if (leaveDays <= 3) {System.out.println("主管批准了" + leaveDays + "天的请假");} else if (next != null) {System.out.println("主管无权处理,转交经理");next.handleRequest(leaveDays);}}
}
// 部门经理处理7天以内的请假
public class Manager extends Handler {@Overridepublic void handleRequest(int leaveDays) {if (leaveDays <= 7) {System.out.println("经理批准了" + leaveDays + "天的请假");} else if (next != null) {System.out.println("经理无权处理,转交总经理");next.handleRequest(leaveDays);}}
}
// 总经理处理所有请假
public class GeneralManager extends Handler {@Overridepublic void handleRequest(int leaveDays) {System.out.println("总经理批准了" + leaveDays + "天的请假");}
}
构建责任链
客户端调用。
public class Client {public static void main(String[] args) {// 构建链条:组长 → 主管 → 经理 → 总经理Handler leader = new TeamLeader();Handler supervisor = new Supervisor();Handler manager = new Manager();Handler generalManager = new GeneralManager();leader.setNext(supervisor);supervisor.setNext(manager);manager.setNext(generalManager);// 发起请求int[] testLeaves = {1, 2, 5, 10};for (int days : testLeaves) {System.out.println("申请" + days + "天请假:");leader.handleRequest(days);System.out.println("------");}}
}
具体输出
申请1天请假:
班组长批准了1天的请假
------
申请2天请假:
班组长无权处理,转交主管
主管批准了2天的请假
------
申请5天请假:
班组长无权处理,转交主管
主管无权处理,转交经理
经理批准了5天的请假
------
申请10天请假:
班组长无权处理,转交主管
主管无权处理,转交经理
经理无权处理,转交总经理
总经理批准了10天的请假
------
五、链式构建器
责任链的高级写法,可以使用链式调用简化链条搭建:
leader.setNext(supervisor).setNext(manager).setNext(generalManager);
为此只需修改 setNext()
方法返回值:
public Handler setNext(Handler next) {this.next = next;return next;
}
六、责任链模式的优缺点
优点:
- 解耦请求发送者和处理者
- 动态组合链条结构,扩展性强
- 处理流程清晰,符合现实逻辑
缺点:
- 可能造成请求无人处理
- 每个处理节点都必须处理转发逻辑
七、实际应用场景
应用场景 | 描述 |
---|---|
Servlet Filter链 | 请求在多个Filter间传递 |
Spring Security拦截链 | 多个拦截器处理登录/权限 |
日志记录 | 日志可传给不同的输出设备 |
OA审批流程 | 按审批等级处理请假/报销等 |
八、小结
责任链模式是非常贴近现实的模式之一,很多审批、拦截、处理流程都可以用它来建模。它解耦了处理者与请求者,使系统更灵活、可拓展。掌握此模式,是 Java 工程师进阶之路的重要一环。
九、参考
《23种设计模式概览》
@startuml
title Java责任链模式结构图(Handler责任链)abstract class Handler {+setNext(next: Handler)+handleRequest(request)-next: Handler
}class LeaderA {班组长
}
class LeaderB {部门主管
}
class LeaderC {总经理
}
class LeaderN {可以加更多节点......
}Handler <|-- LeaderA
Handler <|-- LeaderB
Handler <|-- LeaderCHandler <|-- "LeaderN"@enduml