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);
}
}
这种方式有什么问题呢?
- 代码耦合度高,难以扩展
- 每个处理环节无法复用
- 新增处理环节需要修改核心代码
- 不同的业务场景可能需要不同的处理顺序
二、什么是责任链模式?
责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它为止。
想象一下审批流程:
- 普通员工提交报销申请
- 部门经理审批(小于1000元)
- 总监审批(1000-5000元)
- CEO审批(大于5000元)
每个人只处理自己职责范围内的事情,超出范围就交给下一个处理者。
三、什么是策略模式?
策略模式也是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,使算法的变化独立于使用它们的客户端。
比如支付方式的选择:
- 支付宝支付策略
- 微信支付策略
- 银行卡支付策略
客户端只需要知道要使用哪种策略,而不需要关心具体的实现细节。
四、两种模式如何结合?
将责任链模式和策略模式结合,可以实现更加灵活和可扩展的请求处理机制。
核心思想是:
- 用责任链模式组织处理流程
- 用策略模式实现每个处理环节的具体逻辑
- 通过配置化的方式组装处理链
五、实现思路详解
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. 可以动态开关某些检查环节
结语
通过责任链模式和策略模式的结合,我们可以构建出一个高度灵活、易于扩展的请求处理框架。这种设计不仅解决了传统处理方式的耦合问题,还提供了良好的可维护性和可测试性。
关键要点总结:
- 责任链模式解决处理器的组织和执行顺序问题
- 策略模式解决同一类型处理器的不同实现问题
- 组合使用可以发挥两种模式的最大优势
- 合理设计可以让系统既灵活又稳定
在实际项目中,我们可以根据具体的业务需求来调整这种模式的实现细节,但核心思想是一致的:通过合理的抽象和组合,让复杂的业务逻辑变得清晰可控。
如果你觉得这篇文章对你有帮助,欢迎分享给更多的朋友。在架构设计的路上,我们一起成长!
关注「服务端技术精选」,获取更多干货技术文章!
标题:Java 实现责任链模式 + 策略模式:优雅处理多级请求的方式
作者:jiangyi
地址:http://www.jiangyi.space/articles/2025/12/21/1766304289975.html