用户国营 发表于 2025-4-17 23:32:10

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

1. 责任链模式简介

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



[*] 处理对象独立:每个处理节点(Handler)只关注自己的处理逻辑,无需知道链的结构。
[*] 链式通报:若当前节点无法处理请求,则通报给下一个节点。
[*] 动态设置:链的节点顺序和组合可以在运行时动态调解。
一、入门篇:底子实现与核心机制

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

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

(1)定义抽象处理者
public abstract class LeaveHandler {
    protected LeaveHandler nextHandler;

    // 设置下一个处理节点(链式调用支持)
    public LeaveHandler setNext(LeaveHandler next) {
      this.nextHandler = next;
      return next; // 支持链式调用:supervisor.setNext(manager).setNext(generalManager);
    }

    // 处理请求的抽象方法
    public abstract void handleRequest(LeaveRequest request);
} (2)请求对象封装
public class LeaveRequest {
    private int days;
    private String reason;

    public LeaveRequest(int days) {
      this.days = days;
    }
    // getters & setters
} (3)具体处理者实现
// 主管审批
public class SupervisorHandler extends LeaveHandler {
    @Override
    public void handleRequest(LeaveRequest request) {
      if (request.getDays() <= 3) {
            System.out.println(" Approved: " + request.getDays() + " days");
      } else {
            System.out.println(" Forwarding to next handler...");
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available to process this request!");
            }
      }
    }
}

// 经理审批
public class ManagerHandler extends LeaveHandler {
    @Override
    public void handleRequest(LeaveRequest request) {
      if (request.getDays() <= 7) {
            System.out.println(" Approved: " + request.getDays() + " days");
      } else {
            System.out.println(" Forwarding to next handler...");
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            }
      }
    }
}

// 总经理审批(终结节点)
public class GeneralManagerHandler extends LeaveHandler {
    @Override
    public void handleRequest(LeaveRequest request) {
      System.out.println(" Approved: " + request.getDays() + " days");
    }
} (4)客户端调用与链式构建
public class Client {
    public static void main(String[] args) {
      // 构建责任链(链式调用)
      LeaveHandler supervisor = new SupervisorHandler();
      supervisor.setNext(new ManagerHandler())
                  .setNext(new GeneralManagerHandler());

      // 提交请求
      LeaveRequest request1 = new LeaveRequest(2);
      supervisor.handleRequest(request1);// Supervisor审批

      LeaveRequest request2 = new LeaveRequest(5);
      supervisor.handleRequest(request2);// Manager审批

      LeaveRequest request3 = new LeaveRequest(10);
      supervisor.handleRequest(request3);// General Manager审批
    }
}
3. 责任链模式的关键问题



[*] 终止条件:若不设计终止节点,大概导致请求未被处理。
[*] 性能衡量:链的长度影响处理效率,需制止过长链。
[*] 请求状态管理:是否允许修改请求对象?是否必要通报额外上下文?
二、进阶篇:动态设置与框架集成

1. 动态设置责任链

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

在Spring应用中,可通过@Order注解和List注入实现主动排序。
(1)定义处理接口与上下文对象
public interface RequestHandler {
    boolean handle(RequestContext context);
}

public class RequestContext {
    private boolean handled = false;
    private Map<String, Object> attributes = new HashMap<>();
   
    // 添加属性(用于跨处理器传递数据)
    public void setAttribute(String key, Object value) {
      attributes.put(key, value);
    }
   
    public Object getAttribute(String key) {
      return attributes.get(key);
    }
   
    public void markHandled() {
      this.handled = true;
    }
   
    public boolean isHandled() {
      return handled;
    }
} (2)Spring Bean处理器实现
@Component
@Order(1)
public class ValidationHandler implements RequestHandler {
    @Override
    public boolean handle(RequestContext context) {
      System.out.println("Validating request...");
      if (context.getAttribute("data") == null) {
            throw new IllegalArgumentException("Invalid request data");
      }
      return false; // 未完全处理,继续传递
    }
}

@Component
@Order(2)
public class BusinessLogicHandler implements RequestHandler {
    @Override
    public boolean handle(RequestContext context) {
      System.out.println("Processing business logic...");
      context.markHandled(); // 标记为已处理
      return true; // 终止链
    }
} (3)链实行器
@Component
public class HandlerChainExecutor {
    private final List<RequestHandler> handlers;

    @Autowired
    public HandlerChainExecutor(List<RequestHandler> handlers) {
      this.handlers = handlers.stream()
                .sorted(AnnotationAwareOrderComparator.INSTANCE)
                .collect(Collectors.toList());
    }

    public void execute(RequestContext context) {
      for (RequestHandler handler : handlers) {
            if (handler.handle(context) || context.isHandled()) {
                break; // 终止链
            }
      }
    }
} 三、架构实践:高级应用与性能优化

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

通过责任链模式同一处理日志、权限校验等横切逻辑。
(1)定义切面链
public abstract class AbstractAspectHandler {
    private AbstractAspectHandler next;

    public void setNext(AbstractAspectHandler next) {
      this.next = next;
    }

    public void handle(ProceedingJoinPoint joinPoint) throws Throwable {
      if (canHandle(joinPoint)) {
            doHandle(joinPoint);
      }
      if (next != null) {
            next.handle(joinPoint);
      }
    }

    protected abstract boolean canHandle(ProceedingJoinPoint joinPoint);
    protected abstract void doHandle(ProceedingJoinPoint joinPoint) throws Throwable;
}

// 具体实现:权限校验
public class AuthHandler extends AbstractAspectHandler {
    @Override
    protected boolean canHandle(ProceedingJoinPoint joinPoint) {
      return true; // 所有方法都需要鉴权
    }

    @Override
    protected void doHandle(ProceedingJoinPoint joinPoint) throws Throwable {
      System.out.println("Auth check...");
      // 若鉴权失败,抛出异常
    }
}

// 具体实现:日志记录
public class LogHandler extends AbstractAspectHandler {
    @Override
    protected boolean canHandle(ProceedingJoinPoint joinPoint) {
      return true;
    }

    @Override
    protected void doHandle(ProceedingJoinPoint joinPoint) {
      System.out.println("Logging method call: " + joinPoint.getSignature());
    }
} 2. 在微服务网关中的应用

Spring Cloud Gateway的过滤器链是责任链模式的典型应用。
(1)自定义网关过滤器
@Component
public class RateLimitFilter implements GatewayFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
      if (exceedsRateLimit(exchange)) {
            exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
            return exchange.getResponse().setComplete();
      }
      return chain.filter(exchange);
    }

    private boolean exceedsRateLimit(ServerWebExchange exchange) {
      // 实现限流逻辑
      return false;
    }
}

// 全局过滤器
@Component
public class LoggingFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
      System.out.println("Request path: " + exchange.getRequest().getPath());
      return chain.filter(exchange);
    }
} (2)过滤器设置
spring:
cloud:
    gateway:
      routes:
      - id: service_route
          uri: http://localhost:8080
          predicates:
            - Path=/service/**
          filters:
            - RateLimitFilter
            - RewritePath=/service/(?<segment>.*), /$\{segment} 3. 性能优化策略



[*] 短路机制:某些处理器可中断链(如权限校验失败)。
[*] 异步处理:将非关键处理器改为异步实行(如日志记录)。
[*] 缓存处理器:对无状态处理器实例举行复用。
[*] 并行处理:使用CompletableFuture并行实行独立处理器。
public class ParallelHandlerChain {
    private List<LeaveHandler> handlers = new ArrayList<>();

    public void addHandler(LeaveHandler handler) {
      handlers.add(handler);
    }

    public void handleRequest(LeaveRequest request) {
      handlers.parallelStream()
                .filter(handler -> handler.canHandle(request))
                .findFirst()
                .ifPresent(handler -> handler.handle(request));
    }
} 四、模式变体与扩展

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

利用Lambda和函数式接口简化代码:
public class FunctionalChain {
    private List<Predicate<Request>> validators = new ArrayList<>();
    private List<Consumer<Request>> processors = new ArrayList<>();

    public FunctionalChain addValidator(Predicate<Request> validator) {
      validators.add(validator);
      return this;
    }

    public FunctionalChain addProcessor(Consumer<Request> processor) {
      processors.add(processor);
      return this;
    }

    public boolean execute(Request request) {
      boolean isValid = validators.stream()
                .allMatch(validator -> validator.test(request));
      if (isValid) {
            processors.forEach(processor -> processor.accept(request));
            return true;
      }
      return false;
    }
}

// 使用示例
new FunctionalChain()
    .addValidator(req -> req.getUserId() != null)
    .addValidator(req -> req.getAmount() > 0)
    .addProcessor(req -> System.out.println("Processing: " + req))
    .execute(request); 2. 责任链与模板方法结合

在抽象类中定义处理流程骨架:
public abstract class TemplateHandler {
    private TemplateHandler next;

    public final void handle(Request request) {
      if (canHandle(request)) {
            doHandle(request);
      } else {
            passToNext(request);
      }
    }

    protected abstract boolean canHandle(Request request);
    protected abstract void doHandle(Request request);
   
    protected void passToNext(Request request) {
      if (next != null) {
            next.handle(request);
      } else {
            throw new IllegalStateException("No handler available for request: " + request);
      }
    }
} 五、总结与最佳实践

1. 责任链模式实用场景



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



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



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



[*] 与观察者模式结合:处理器处理完成后发布变乱。
[*] 分布式责任链:通过消息队列将处理器分布在多个服务中。
[*] 设置中央集成:动态更新处理链设置(如Apollo、Nacos)。
通过深入理解责任链模式的核心机制,并结合实际业务需求灵活扩展,开发者可以构建出高内聚、低耦合、易维护的处理流程,有效应对复杂业务场景的挑战。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Java设计模式之责任链模式:从入门到架构级实践