Java 实现责任链模式 + 策略模式:优雅处理多级请求的方式

Java 实现责任链模式 + 策略模式:优雅处理多级请求的方式

一个请求需要经过多个处理环节,每个环节都有不同的判断逻辑,代码写得像意大利面条一样混乱?今天我就来分享一种优雅的解决方案——责任链模式 + 策略模式的组合拳。

一、为什么要用这两种设计模式?

在开始技术实现之前,我们先来思考一个问题:当一个复杂的业务请求需要经过多个处理节点时,我们通常会怎么做?

// 传统的处理方式(不推荐)
public class TraditionalProcessor {
    public void process(Request request) {
        // 第一步:参数校验
        if (!validateParams(request)) {
            throw new IllegalArgumentException("参数校验失败");
        }
        
        // 第二步:权限检查
        if (!checkPermission(request)) {
            throw new SecurityException("权限不足");
        }
        
        // 第三步:业务规则校验
        if (!validateBusinessRules(request)) {
            throw new BusinessException("业务规则校验失败");
        }
        
        // 第四步:执行业务逻辑
        doBusinessLogic(request);
    }
}

这种方式有什么问题呢?

  1. 代码耦合度高,难以扩展
  2. 每个处理环节无法复用
  3. 新增处理环节需要修改核心代码
  4. 不同的业务场景可能需要不同的处理顺序

二、什么是责任链模式?

责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它为止。

想象一下审批流程:

  • 普通员工提交报销申请
  • 部门经理审批(小于1000元)
  • 总监审批(1000-5000元)
  • CEO审批(大于5000元)

每个人只处理自己职责范围内的事情,超出范围就交给下一个处理者。

三、什么是策略模式?

策略模式也是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,使算法的变化独立于使用它们的客户端。

比如支付方式的选择:

  • 支付宝支付策略
  • 微信支付策略
  • 银行卡支付策略

客户端只需要知道要使用哪种策略,而不需要关心具体的实现细节。

四、两种模式如何结合?

将责任链模式和策略模式结合,可以实现更加灵活和可扩展的请求处理机制。

核心思想是:

  1. 用责任链模式组织处理流程
  2. 用策略模式实现每个处理环节的具体逻辑
  3. 通过配置化的方式组装处理链

五、实现思路详解

5.1 定义统一的处理接口

首先我们需要定义一个统一的处理器接口:

// 处理器接口
public interface RequestHandler {
    /**
     * 处理请求
     * @param context 请求上下文
     * @return 是否继续处理
     */
    boolean handle(RequestContext context);
    
    /**
     * 获取处理器名称
     */
    String getName();
}

5.2 定义请求上下文

为了在处理链中传递数据,我们需要一个上下文对象:

// 请求上下文
public class RequestContext {
    private Map<String, Object> attributes = new HashMap<>();
    private Object requestData;
    private Object responseData;
    private List<String> processLog = new ArrayList<>();
    
    // getter/setter方法...
    
    public void addProcessLog(String log) {
        processLog.add(log);
    }
}

5.3 实现责任链接口

接下来实现责任链的核心逻辑:

// 责任链接口
public abstract class AbstractHandlerChain implements RequestHandler {
    protected RequestHandler nextHandler;
    
    public void setNextHandler(RequestHandler handler) {
        this.nextHandler = handler;
    }
    
    @Override
    public boolean handle(RequestContext context) {
        // 当前处理器处理
        boolean result = doHandle(context);
        
        // 如果处理成功且有下一个处理器,则继续处理
        if (result && nextHandler != null) {
            return nextHandler.handle(context);
        }
        
        return result;
    }
    
    // 子类需要实现的具体处理逻辑
    protected abstract boolean doHandle(RequestContext context);
}

5.4 实现具体的处理器

现在我们可以实现各种具体的处理器了:

// 参数校验处理器
@Component
public class ParameterValidationHandler extends AbstractHandlerChain {
    
    @Override
    public String getName() {
        return "参数校验处理器";
    }
    
    @Override
    protected boolean doHandle(RequestContext context) {
        // 获取请求数据
        Object requestData = context.getRequestData();
        
        // 执行参数校验逻辑
        if (requestData == null) {
            context.addProcessLog("参数为空,校验失败");
            return false;
        }
        
        // 更多校验逻辑...
        context.addProcessLog("参数校验通过");
        return true;
    }
}

// 权限检查处理器
@Component
public class PermissionCheckHandler extends AbstractHandlerChain {
    
    @Override
    public String getName() {
        return "权限检查处理器";
    }
    
    @Override
    protected boolean doHandle(RequestContext context) {
        // 获取用户信息
        String userId = (String) context.getAttribute("userId");
        
        // 执行权限检查逻辑
        if (!hasPermission(userId)) {
            context.addProcessLog("用户权限不足");
            return false;
        }
        
        context.addProcessLog("权限检查通过");
        return true;
    }
    
    private boolean hasPermission(String userId) {
        // 实际的权限检查逻辑
        return true; // 简化示例
    }
}

5.5 策略模式的应用

对于同一类型的处理器,我们可以用策略模式来实现不同的处理策略:

// 业务规则校验策略接口
public interface BusinessRuleStrategy {
    boolean validate(RequestContext context);
    String getRuleName();
}

// 订单金额校验策略
@Component
public class OrderAmountRuleStrategy implements BusinessRuleStrategy {
    
    @Override
    public boolean validate(RequestContext context) {
        // 获取订单信息
        OrderInfo orderInfo = (OrderInfo) context.getRequestData();
        
        // 校验金额是否合理
        if (orderInfo.getAmount().compareTo(BigDecimal.valueOf(100000)) > 0) {
            context.addProcessLog("订单金额过大");
            return false;
        }
        
        return true;
    }
    
    @Override
    public String getRuleName() {
        return "订单金额校验";
    }
}

// 库存校验策略
@Component
public class InventoryRuleStrategy implements BusinessRuleStrategy {
    
    @Override
    public boolean validate(RequestContext context) {
        // 获取商品信息
        ProductInfo productInfo = (ProductInfo) context.getRequestData();
        
        // 校验库存是否充足
        if (productInfo.getStock() < productInfo.getQuantity()) {
            context.addProcessLog("库存不足");
            return false;
        }
        
        return true;
    }
    
    @Override
    public String getRuleName() {
        return "库存校验";
    }
}

// 业务规则校验处理器(使用策略模式)
@Component
public class BusinessRuleHandler extends AbstractHandlerChain {
    
    @Autowired
    private List<BusinessRuleStrategy> strategies;
    
    @Override
    public String getName() {
        return "业务规则校验处理器";
    }
    
    @Override
    protected boolean doHandle(RequestContext context) {
        // 依次执行所有业务规则策略
        for (BusinessRuleStrategy strategy : strategies) {
            if (!strategy.validate(context)) {
                context.addProcessLog("业务规则校验失败: " + strategy.getRuleName());
                return false;
            }
            context.addProcessLog("业务规则校验通过: " + strategy.getRuleName());
        }
        
        return true;
    }
}

5.6 链的组装和管理

为了让责任链更加灵活,我们需要一个链的管理器:

// 处理链管理器
@Component
public class HandlerChainManager {
    
    @Autowired
    private List<RequestHandler> handlers;
    
    // 根据配置组装处理链
    public RequestHandler buildChain(List<String> handlerNames) {
        if (handlerNames == null || handlerNames.isEmpty()) {
            return null;
        }
        
        RequestHandler head = null;
        RequestHandler current = null;
        
        for (String handlerName : handlerNames) {
            RequestHandler handler = findHandlerByName(handlerName);
            if (handler != null) {
                if (head == null) {
                    head = handler;
                    current = handler;
                } else {
                    ((AbstractHandlerChain) current).setNextHandler(handler);
                    current = handler;
                }
            }
        }
        
        return head;
    }
    
    private RequestHandler findHandlerByName(String name) {
        return handlers.stream()
                .filter(h -> h.getName().equals(name))
                .findFirst()
                .orElse(null);
    }
}

六、使用示例

现在让我们看看如何使用这套机制:

// 服务类
@Service
public class RequestProcessingService {
    
    @Autowired
    private HandlerChainManager chainManager;
    
    public ProcessResult processRequest(Object requestData) {
        // 创建请求上下文
        RequestContext context = new RequestContext();
        context.setRequestData(requestData);
        context.setAttribute("userId", getCurrentUserId());
        
        // 定义处理链顺序
        List<String> handlerSequence = Arrays.asList(
            "参数校验处理器",
            "权限检查处理器",
            "业务规则校验处理器",
            "业务逻辑处理器"
        );
        
        // 组装处理链
        RequestHandler chain = chainManager.buildChain(handlerSequence);
        
        // 执行处理
        boolean success = chain != null && chain.handle(context);
        
        // 返回处理结果
        return ProcessResult.builder()
                .success(success)
                .processLogs(context.getProcessLog())
                .responseData(context.getResponseData())
                .build();
    }
    
    private String getCurrentUserId() {
        // 获取当前用户ID的逻辑
        return "USER001";
    }
}

七、优势分析

这种设计模式组合有哪些优势呢?

7.1 高内聚低耦合

每个处理器只关注自己的职责,不关心其他处理器的实现细节:

优势分析:
1. 单一职责:每个处理器职责单一,易于理解和维护
2. 松耦合:处理器之间通过接口交互,降低耦合度
3. 易于测试:每个处理器可以独立进行单元测试

7.2 高度可扩展

新增处理器或修改处理顺序都非常简单:

扩展性优势:
1. 新增处理器:只需实现RequestHandler接口
2. 修改顺序:通过配置调整处理链顺序
3. 动态组装:可以根据不同场景动态组装不同的处理链

7.3 灵活的策略组合

策略模式使得业务规则可以灵活组合:

策略模式优势:
1. 算法复用:相同的策略可以在不同场景下复用
2. 易于替换:可以方便地替换某个策略实现
3. 扩展性强:新增策略不影响现有代码

八、性能考虑

在实际应用中,我们还需要考虑一些性能问题:

8.1 处理器缓存

为了避免每次都重新组装处理链,我们可以加入缓存机制:

// 带缓存的处理链管理器
@Component
public class CachedHandlerChainManager {
    
    private final Map<String, RequestHandler> chainCache = new ConcurrentHashMap<>();
    
    public RequestHandler getOrCreateChain(String chainKey, List<String> handlerNames) {
        return chainCache.computeIfAbsent(chainKey, k -> buildChain(handlerNames));
    }
}

8.2 异常处理

在责任链中,我们需要合理处理异常:

// 带异常处理的责任链接口
public abstract class ExceptionSafeHandlerChain extends AbstractHandlerChain {
    
    @Override
    public boolean handle(RequestContext context) {
        try {
            boolean result = doHandle(context);
            
            if (result && nextHandler != null) {
                return nextHandler.handle(context);
            }
            
            return result;
        } catch (Exception e) {
            // 记录异常日志
            context.addProcessLog("处理器执行异常: " + getName() + ", 错误: " + e.getMessage());
            // 根据业务需求决定是否继续执行下一个处理器
            return handleException(e, context);
        }
    }
    
    protected boolean handleException(Exception e, RequestContext context) {
        // 默认情况下,异常会导致处理链中断
        return false;
    }
}

九、最佳实践建议

9.1 设计原则

设计原则总结:
1. 开闭原则:对扩展开放,对修改关闭
2. 单一职责:每个处理器只负责一个特定的功能
3. 里氏替换:子类可以替换父类而不影响程序正确性
4. 接口隔离:使用专门的接口而不是胖接口
5. 依赖倒置:依赖抽象而不是具体实现

9.2 实施建议

实施建议:
1. 合理划分处理器粒度:不要过细也不要过粗
2. 统一异常处理机制:建立统一的异常处理框架
3. 完善日志记录:详细记录每个处理器的执行情况
4. 性能监控:监控每个处理器的执行时间和资源消耗
5. 配置管理:通过配置文件管理处理链的组装规则

十、应用场景举例

这种模式特别适用于以下场景:

10.1 订单处理系统

订单处理场景:
1. 参数校验 → 权限检查 → 库存校验 → 价格计算 → 支付处理 → 订单创建
2. 不同类型的订单可以有不同的处理链
3. 可以动态调整处理顺序

10.2 用户注册流程

用户注册场景:
1. 数据格式校验 → 验证码校验 → 用户名唯一性检查 → 密码强度校验 → 用户创建 → 发送欢迎邮件
2. 不同渠道的注册可以有不同的校验规则
3. 可以根据用户类型调整处理流程

10.3 API网关鉴权

API网关场景:
1. IP黑白名单检查 → Token验证 → 权限校验 → 限流检查 → 转发请求
2. 不同API可以配置不同的鉴权策略
3. 可以动态开关某些检查环节

结语

通过责任链模式和策略模式的结合,我们可以构建出一个高度灵活、易于扩展的请求处理框架。这种设计不仅解决了传统处理方式的耦合问题,还提供了良好的可维护性和可测试性。

关键要点总结:

  1. 责任链模式解决处理器的组织和执行顺序问题
  2. 策略模式解决同一类型处理器的不同实现问题
  3. 组合使用可以发挥两种模式的最大优势
  4. 合理设计可以让系统既灵活又稳定

在实际项目中,我们可以根据具体的业务需求来调整这种模式的实现细节,但核心思想是一致的:通过合理的抽象和组合,让复杂的业务逻辑变得清晰可控。

如果你觉得这篇文章对你有帮助,欢迎分享给更多的朋友。在架构设计的路上,我们一起成长!


关注「服务端技术精选」,获取更多干货技术文章!


标题:Java 实现责任链模式 + 策略模式:优雅处理多级请求的方式
作者:jiangyi
地址:http://jiangyi.space/articles/2025/12/21/1766304289975.html

    0 评论
avatar