如何使用职责链模式进行代码重构?
业务场景
电商下单前需要进行一系列校验:用户状态、商品库存、优惠券、限购规则、风控等。
原代码问题
public class OrderValidator {
public void validate(OrderRequest request) {
// 1. 用户校验
User user = userService.getUser(request.getUserId());
if (user == null || user.getStatus() != 1) {
throw new ValidationException("用户状态异常");
}
// 2. 库存校验
Stock stock = stockService.getStock(request.getProductId());
if (stock.getCount() < request.getQuantity()) {
throw new ValidationException("库存不足");
}
// 3. 优惠券校验
if (request.getCouponId() != null) {
Coupon coupon = couponService.getCoupon(request.getCouponId());
if (coupon.isExpired() || coupon.isUsed()) {
throw new ValidationException("优惠券不可用");
}
}
// 4. 限购校验
int purchased = orderService.countUserOrders(request);
if (purchased >= 5) {
throw new ValidationException("超出限购数量");
}
// 5. 风控校验
RiskResult risk = riskService.check(request);
if (risk.isBlocked()) {
throw new ValidationException("风控拦截");
}
// 还有更多...
}
}
问题:
- 校验逻辑全部堆在一起,违反单一职责
- 新增/修改校验需要修改核心类
- 无法灵活调整校验顺序
- 难以复用单个校验逻辑
职责链模式解决方案
模式定义
将请求沿着处理者链传递,每个处理者决定是否处理请求以及是否传递给下一个处理者。
设计结构
请求 → Handler1 → Handler2 → Handler3 → ... → 完成
│ │ │
处理/拒绝 处理/拒绝 处理/拒绝
重构后代码
抽象处理器
public abstract class OrderValidationHandler {
protected OrderValidationHandler next;
public void setNext(OrderValidationHandler next) {
this.next = next;
}
public void validate(OrderRequest request) {
doValidate(request);
if (next != null) {
next.validate(request);
}
}
protected abstract void doValidate(OrderRequest request);
}
具体处理器
// 用户校验
@Component
@Order(1)
public class UserValidationHandler extends OrderValidationHandler {
@Autowired
private UserService userService;
@Override
protected void doValidate(OrderRequest request) {
User user = userService.getUser(request.getUserId());
if (user == null || user.getStatus() != 1) {
throw new ValidationException("用户状态异常");
}
}
}
// 库存校验
@Component
@Order(2)
public class StockValidationHandler extends OrderValidationHandler {
@Autowired
private StockService stockService;
@Override
protected void doValidate(OrderRequest request) {
Stock stock = stockService.getStock(request.getProductId());
if (stock.getCount() < request.getQuantity()) {
throw new ValidationException("库存不足");
}
}
}
// 优惠券校验
@Component
@Order(3)
public class CouponValidationHandler extends OrderValidationHandler {
@Autowired
private CouponService couponService;
@Override
protected void doValidate(OrderRequest request) {
if (request.getCouponId() == null) {
return; // 无优惠券直接跳过
}
Coupon coupon = couponService.getCoupon(request.getCouponId());
if (coupon.isExpired() || coupon.isUsed()) {
throw new ValidationException("优惠券不可用");
}
}
}
// 限购校验
@Component
@Order(4)
public class LimitValidationHandler extends OrderValidationHandler {
@Override
protected void doValidate(OrderRequest request) {
int purchased = orderService.countUserOrders(request);
if (purchased >= 5) {
throw new ValidationException("超出限购数量");
}
}
}
// 风控校验
@Component
@Order(5)
public class RiskValidationHandler extends OrderValidationHandler {
@Autowired
private RiskService riskService;
@Override
protected void doValidate(OrderRequest request) {
RiskResult risk = riskService.check(request);
if (risk.isBlocked()) {
throw new ValidationException("风控拦截: " + risk.getReason());
}
}
}
链构建与使用
@Configuration
public class ValidationChainConfig {
@Autowired
private List<OrderValidationHandler> handlers;
@Bean
public OrderValidationHandler validationChain() {
// 按@Order排序
handlers.sort(Comparator.comparingInt(
h -> h.getClass().getAnnotation(Order.class).value()));
// 构建链
for (int i = 0; i < handlers.size() - 1; i++) {
handlers.get(i).setNext(handlers.get(i + 1));
}
return handlers.get(0);
}
}
@Service
public class OrderService {
@Autowired
private OrderValidationHandler validationChain;
public Order createOrder(OrderRequest request) {
// 执行校验链
validationChain.validate(request);
// 校验通过,创建订单
return doCreateOrder(request);
}
}
进阶:动态配置校验规则
通过配置控制校验开关
order:
validation:
user: true
stock: true
coupon: true
limit: false # 大促期间关闭限购
risk: true
@Component
@Order(4)
@ConditionalOnProperty(name = "order.validation.limit", havingValue = "true")
public class LimitValidationHandler extends OrderValidationHandler {
// ...
}
通过数据库配置规则
@Component
public class DynamicValidationChain {
@Autowired
private Map<String, OrderValidationHandler> handlerMap;
public void validate(OrderRequest request) {
// 从数据库读取启用的规则
List<String> enabledRules = configService.getEnabledRules();
for (String rule : enabledRules) {
OrderValidationHandler handler = handlerMap.get(rule);
if (handler != null) {
handler.doValidate(request);
}
}
}
}
优化效果
| 指标 | 重构前 | 重构后 |
|---|---|---|
| 核心类代码行 | 150行 | 10行 |
| 新增校验改动点 | 1处核心类 | 新增1个类 |
| 校验逻辑复用 | 不可复用 | 可独立复用 |
| 顺序调整 | 需改代码 | 改@Order注解 |
| 动态开关 | 不支持 | 支持 |
面试答题框架
业务场景:下单前多步骤校验
原代码问题:
- 违反单一职责
- 扩展需改核心类
- 无法灵活调整顺序
重构方案:职责链模式
- 抽象Handler定义校验接口
- 具体Handler实现各校验逻辑
- 链式调用,逐个校验
扩展能力:
- @Order控制顺序
- 配置中心动态开关
- 新增校验只需增加类
总结
| 要点 | 说明 |
|---|---|
| 适用场景 | 多步骤处理,顺序可变 |
| 核心思想 | 请求沿链传递 |
| 优点 | 解耦、可扩展、可配置 |
| 变体 | 拦截器链、过滤器链 |