Java设计模式之责任链模式:从入门到架构级实践

打印 上一主题 下一主题

主题 1621|帖子 1621|积分 4863

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. 责任链模式简介

责任链模式(Chain of Responsibility Pattern)是一种活动设计模式,允许将请求沿着处理链通报,直到某个处理对象可以或许处理它。这种模式通过解耦请求的发送者和接收者,提供动态扩展处理逻辑的能力。责任链模式广泛应用于日志处理、权限校验、过滤器链(如Servlet Filter)、工作流审批等场景。
2. 责任链模式核心头脑



  • 处理对象独立:每个处理节点(Handler)只关注自己的处理逻辑,无需知道链的结构。
  • 链式通报:若当前节点无法处理请求,则通报给下一个节点。
  • 动态设置:链的节点顺序和组合可以在运行时动态调解。

一、入门篇:底子实现与核心机制

1. 场景示例:请假审批流程

假设公司请假审批流程为:员工提交请假申请,需依次经过 主管 → 经理 → 总经理 三级审批,天数限定分别为3天、7天和无穷。
2. 传统实现方式

(1)定义抽象处理者
  1. public abstract class LeaveHandler {
  2.     protected LeaveHandler nextHandler;
  3.     // 设置下一个处理节点(链式调用支持)
  4.     public LeaveHandler setNext(LeaveHandler next) {
  5.         this.nextHandler = next;
  6.         return next; // 支持链式调用:supervisor.setNext(manager).setNext(generalManager);
  7.     }
  8.     // 处理请求的抽象方法
  9.     public abstract void handleRequest(LeaveRequest request);
  10. }
复制代码
(2)请求对象封装
  1. public class LeaveRequest {
  2.     private int days;
  3.     private String reason;
  4.     public LeaveRequest(int days) {
  5.         this.days = days;
  6.     }
  7.     // getters & setters
  8. }
复制代码
(3)具体处理者实现
  1. // 主管审批
  2. public class SupervisorHandler extends LeaveHandler {
  3.     @Override
  4.     public void handleRequest(LeaveRequest request) {
  5.         if (request.getDays() <= 3) {
  6.             System.out.println("[Supervisor] Approved: " + request.getDays() + " days");
  7.         } else {
  8.             System.out.println("[Supervisor] Forwarding to next handler...");
  9.             if (nextHandler != null) {
  10.                 nextHandler.handleRequest(request);
  11.             } else {
  12.                 System.out.println("No handler available to process this request!");
  13.             }
  14.         }
  15.     }
  16. }
  17. // 经理审批
  18. public class ManagerHandler extends LeaveHandler {
  19.     @Override
  20.     public void handleRequest(LeaveRequest request) {
  21.         if (request.getDays() <= 7) {
  22.             System.out.println("[Manager] Approved: " + request.getDays() + " days");
  23.         } else {
  24.             System.out.println("[Manager] Forwarding to next handler...");
  25.             if (nextHandler != null) {
  26.                 nextHandler.handleRequest(request);
  27.             }
  28.         }
  29.     }
  30. }
  31. // 总经理审批(终结节点)
  32. public class GeneralManagerHandler extends LeaveHandler {
  33.     @Override
  34.     public void handleRequest(LeaveRequest request) {
  35.         System.out.println("[General Manager] Approved: " + request.getDays() + " days");
  36.     }
  37. }
复制代码
(4)客户端调用与链式构建
  1. public class Client {
  2.     public static void main(String[] args) {
  3.         // 构建责任链(链式调用)
  4.         LeaveHandler supervisor = new SupervisorHandler();
  5.         supervisor.setNext(new ManagerHandler())
  6.                   .setNext(new GeneralManagerHandler());
  7.         // 提交请求
  8.         LeaveRequest request1 = new LeaveRequest(2);
  9.         supervisor.handleRequest(request1);  // Supervisor审批
  10.         LeaveRequest request2 = new LeaveRequest(5);
  11.         supervisor.handleRequest(request2);  // Manager审批
  12.         LeaveRequest request3 = new LeaveRequest(10);
  13.         supervisor.handleRequest(request3);  // General Manager审批
  14.     }
  15. }
复制代码

3. 责任链模式的关键问题



  • 终止条件:若不设计终止节点,大概导致请求未被处理。
  • 性能衡量:链的长度影响处理效率,需制止过长链。
  • 请求状态管理:是否允许修改请求对象?是否必要通报额外上下文?

二、进阶篇:动态设置与框架集成

1. 动态设置责任链

实际项目中,处理链的节点大概必要通过设置文件或数据库动态加载。
(1)设置文件定义节点顺序
  1. # handler-chain.properties
  2. handler.order=supervisor,manager,generalManager
  3. handler.supervisor.class=com.example.SupervisorHandler
  4. handler.manager.class=com.example.ManagerHandler
  5. handler.generalManager.class=com.example.GeneralManagerHandler
复制代码
(2)工厂类反射构建链
  1. public class HandlerChainFactory {
  2.     public static LeaveHandler createChain() throws Exception {
  3.         Properties props = new Properties();
  4.         props.load(HandlerChainFactory.class.getResourceAsStream("/handler-chain.properties"));
  5.         
  6.         String[] handlerOrder = props.getProperty("handler.order").split(",");
  7.         LeaveHandler first = null, current = null;
  8.         
  9.         for (String key : handlerOrder) {
  10.             String className = props.getProperty("handler." + key + ".class");
  11.             Class<?> clazz = Class.forName(className);
  12.             LeaveHandler handler = (LeaveHandler) clazz.getDeclaredConstructor().newInstance();
  13.             
  14.             if (first == null) {
  15.                 first = current = handler;
  16.             } else {
  17.                 current.setNext(handler);
  18.                 current = handler;
  19.             }
  20.         }
  21.         return first;
  22.     }
  23. }
复制代码
2. 结合Spring框架的依赖注入

在Spring应用中,可通过@Order注解和List注入实现主动排序。
(1)定义处理接口与上下文对象
  1. public interface RequestHandler {
  2.     boolean handle(RequestContext context);
  3. }
  4. public class RequestContext {
  5.     private boolean handled = false;
  6.     private Map<String, Object> attributes = new HashMap<>();
  7.    
  8.     // 添加属性(用于跨处理器传递数据)
  9.     public void setAttribute(String key, Object value) {
  10.         attributes.put(key, value);
  11.     }
  12.    
  13.     public Object getAttribute(String key) {
  14.         return attributes.get(key);
  15.     }
  16.    
  17.     public void markHandled() {
  18.         this.handled = true;
  19.     }
  20.    
  21.     public boolean isHandled() {
  22.         return handled;
  23.     }
  24. }
复制代码
(2)Spring Bean处理器实现
  1. @Component
  2. @Order(1)
  3. public class ValidationHandler implements RequestHandler {
  4.     @Override
  5.     public boolean handle(RequestContext context) {
  6.         System.out.println("Validating request...");
  7.         if (context.getAttribute("data") == null) {
  8.             throw new IllegalArgumentException("Invalid request data");
  9.         }
  10.         return false; // 未完全处理,继续传递
  11.     }
  12. }
  13. @Component
  14. @Order(2)
  15. public class BusinessLogicHandler implements RequestHandler {
  16.     @Override
  17.     public boolean handle(RequestContext context) {
  18.         System.out.println("Processing business logic...");
  19.         context.markHandled(); // 标记为已处理
  20.         return true; // 终止链
  21.     }
  22. }
复制代码
(3)链实行器
  1. @Component
  2. public class HandlerChainExecutor {
  3.     private final List<RequestHandler> handlers;
  4.     @Autowired
  5.     public HandlerChainExecutor(List<RequestHandler> handlers) {
  6.         this.handlers = handlers.stream()
  7.                 .sorted(AnnotationAwareOrderComparator.INSTANCE)
  8.                 .collect(Collectors.toList());
  9.     }
  10.     public void execute(RequestContext context) {
  11.         for (RequestHandler handler : handlers) {
  12.             if (handler.handle(context) || context.isHandled()) {
  13.                 break; // 终止链
  14.             }
  15.         }
  16.     }
  17. }
复制代码

三、架构实践:高级应用与性能优化

1. 结合AOP实现横切关注点

通过责任链模式同一处理日志、权限校验等横切逻辑。
(1)定义切面链
  1. public abstract class AbstractAspectHandler {
  2.     private AbstractAspectHandler next;
  3.     public void setNext(AbstractAspectHandler next) {
  4.         this.next = next;
  5.     }
  6.     public void handle(ProceedingJoinPoint joinPoint) throws Throwable {
  7.         if (canHandle(joinPoint)) {
  8.             doHandle(joinPoint);
  9.         }
  10.         if (next != null) {
  11.             next.handle(joinPoint);
  12.         }
  13.     }
  14.     protected abstract boolean canHandle(ProceedingJoinPoint joinPoint);
  15.     protected abstract void doHandle(ProceedingJoinPoint joinPoint) throws Throwable;
  16. }
  17. // 具体实现:权限校验
  18. public class AuthHandler extends AbstractAspectHandler {
  19.     @Override
  20.     protected boolean canHandle(ProceedingJoinPoint joinPoint) {
  21.         return true; // 所有方法都需要鉴权
  22.     }
  23.     @Override
  24.     protected void doHandle(ProceedingJoinPoint joinPoint) throws Throwable {
  25.         System.out.println("Auth check...");
  26.         // 若鉴权失败,抛出异常
  27.     }
  28. }
  29. // 具体实现:日志记录
  30. public class LogHandler extends AbstractAspectHandler {
  31.     @Override
  32.     protected boolean canHandle(ProceedingJoinPoint joinPoint) {
  33.         return true;
  34.     }
  35.     @Override
  36.     protected void doHandle(ProceedingJoinPoint joinPoint) {
  37.         System.out.println("Logging method call: " + joinPoint.getSignature());
  38.     }
  39. }
复制代码
2. 在微服务网关中的应用

Spring Cloud Gateway的过滤器链是责任链模式的典型应用。
(1)自定义网关过滤器
  1. @Component
  2. public class RateLimitFilter implements GatewayFilter {
  3.     @Override
  4.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  5.         if (exceedsRateLimit(exchange)) {
  6.             exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
  7.             return exchange.getResponse().setComplete();
  8.         }
  9.         return chain.filter(exchange);
  10.     }
  11.     private boolean exceedsRateLimit(ServerWebExchange exchange) {
  12.         // 实现限流逻辑
  13.         return false;
  14.     }
  15. }
  16. // 全局过滤器
  17. @Component
  18. public class LoggingFilter implements GlobalFilter {
  19.     @Override
  20.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  21.         System.out.println("Request path: " + exchange.getRequest().getPath());
  22.         return chain.filter(exchange);
  23.     }
  24. }
复制代码
(2)过滤器设置
  1. spring:
  2.   cloud:
  3.     gateway:
  4.       routes:
  5.         - id: service_route
  6.           uri: http://localhost:8080
  7.           predicates:
  8.             - Path=/service/**
  9.           filters:
  10.             - RateLimitFilter
  11.             - RewritePath=/service/(?<segment>.*), /$\{segment}
复制代码
3. 性能优化策略



  • 短路机制:某些处理器可中断链(如权限校验失败)。
  • 异步处理:将非关键处理器改为异步实行(如日志记录)。
  • 缓存处理器:对无状态处理器实例举行复用。
  • 并行处理:使用CompletableFuture并行实行独立处理器。
  1. public class ParallelHandlerChain {
  2.     private List<LeaveHandler> handlers = new ArrayList<>();
  3.     public void addHandler(LeaveHandler handler) {
  4.         handlers.add(handler);
  5.     }
  6.     public void handleRequest(LeaveRequest request) {
  7.         handlers.parallelStream()
  8.                 .filter(handler -> handler.canHandle(request))
  9.                 .findFirst()
  10.                 .ifPresent(handler -> handler.handle(request));
  11.     }
  12. }
复制代码

四、模式变体与扩展

1. 功能式责任链(Java 8+)

利用Lambda和函数式接口简化代码:
  1. public class FunctionalChain {
  2.     private List<Predicate<Request>> validators = new ArrayList<>();
  3.     private List<Consumer<Request>> processors = new ArrayList<>();
  4.     public FunctionalChain addValidator(Predicate<Request> validator) {
  5.         validators.add(validator);
  6.         return this;
  7.     }
  8.     public FunctionalChain addProcessor(Consumer<Request> processor) {
  9.         processors.add(processor);
  10.         return this;
  11.     }
  12.     public boolean execute(Request request) {
  13.         boolean isValid = validators.stream()
  14.                 .allMatch(validator -> validator.test(request));
  15.         if (isValid) {
  16.             processors.forEach(processor -> processor.accept(request));
  17.             return true;
  18.         }
  19.         return false;
  20.     }
  21. }
  22. // 使用示例
  23. new FunctionalChain()
  24.     .addValidator(req -> req.getUserId() != null)
  25.     .addValidator(req -> req.getAmount() > 0)
  26.     .addProcessor(req -> System.out.println("Processing: " + req))
  27.     .execute(request);
复制代码
2. 责任链与模板方法结合

在抽象类中定义处理流程骨架:
  1. public abstract class TemplateHandler {
  2.     private TemplateHandler next;
  3.     public final void handle(Request request) {
  4.         if (canHandle(request)) {
  5.             doHandle(request);
  6.         } else {
  7.             passToNext(request);
  8.         }
  9.     }
  10.     protected abstract boolean canHandle(Request request);
  11.     protected abstract void doHandle(Request request);
  12.    
  13.     protected void passToNext(Request request) {
  14.         if (next != null) {
  15.             next.handle(request);
  16.         } else {
  17.             throw new IllegalStateException("No handler available for request: " + request);
  18.         }
  19.     }
  20. }
复制代码

五、总结与最佳实践

1. 责任链模式实用场景



  • 多级审批流程:如请假、报销审批。
  • 可插拔处理逻辑:如HTTP请求处理管道。
  • 横切关注点分离:如日志、安全、事务管理。
2. 反模式与注意事项



  • 制止循环依赖:处理器之间不应形成循环引用。
  • 明确终止条件:防止请求未被处理导致内存泄漏。
  • 控制链的长度:过长的链会增加调试难度。
3. 调试技巧



  • 唯一标识:为每个处理器添加ID,便于日志追踪。
  • 链可视化:实现toString()方法输出链结构。
  1. public class SupervisorHandler extends LeaveHandler {
  2.     @Override
  3.     public String toString() {
  4.         return "SupervisorHandler -> " + (nextHandler != null ? nextHandler.toString() : "null");
  5.     }
  6. }
复制代码
4. 扩展方向



  • 与观察者模式结合:处理器处理完成后发布变乱。
  • 分布式责任链:通过消息队列将处理器分布在多个服务中。
  • 设置中央集成:动态更新处理链设置(如Apollo、Nacos)。

通过深入理解责任链模式的核心机制,并结合实际业务需求灵活扩展,开发者可以构建出高内聚、低耦合、易维护的处理流程,有效应对复杂业务场景的挑战。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表