深入实战模板方法模式与装饰器模式:模板方法模式与装饰器模式在电商系统中的应用

我将分享两种不太常见但非常实用的设计模式在Spring Boot项目中的实际应用:模板方法模式和装饰器模式。这些模式在电商系统中能优雅地解决一些特定问题。

1. 模板方法模式在订单处理流程中的应用

业务场景

电商系统中,不同类型的订单(普通订单、团购订单、秒杀订单)有相似的处理流程,但某些步骤的实现细节不同。例如:

  1. 所有订单都需要验证、计算价格、扣减库存、创建支付
  2. 但团购订单需要额外验证成团状态
  3. 秒杀订单需要验证秒杀资格

代码实现

定义订单处理的抽象模板:

java 复制代码
public abstract class AbstractOrderProcessor {
    
    // 模板方法,定义处理流程
    public final OrderProcessResult process(OrderContext context) {
        validate(context);
        calculatePrice(context);
        if (needSpecificCheck(context)) {
            specificCheck(context);
        }
        deductInventory(context);
        createPayment(context);
        return buildResult(context);
    }
    
    // 通用步骤
    protected void validate(OrderContext context) {
        // 通用验证逻辑
        if (context.getItems().isEmpty()) {
            throw new IllegalArgumentException("订单商品不能为空");
        }
    }
    
    protected void calculatePrice(OrderContext context) {
        // 通用价格计算逻辑
        BigDecimal total = context.getItems().stream()
                .map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        context.setTotalAmount(total);
    }
    
    protected void deductInventory(OrderContext context) {
        // 通用库存扣减逻辑
        inventoryService.batchDeduct(context.getItems());
    }
    
    protected void createPayment(OrderContext context) {
        // 通用支付创建逻辑
        paymentService.createPayment(context.getOrderId(), context.getTotalAmount());
    }
    
    protected OrderProcessResult buildResult(OrderContext context) {
        return new OrderProcessResult(true, "订单处理成功", context.getOrderId());
    }
    
    // 钩子方法,子类可覆盖
    protected boolean needSpecificCheck(OrderContext context) {
        return false;
    }
    
    // 抽象方法,子类必须实现
    protected abstract void specificCheck(OrderContext context);
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
}

实现具体订单处理器:

java 复制代码
@Service
public class NormalOrderProcessor extends AbstractOrderProcessor {
    @Override
    protected void specificCheck(OrderContext context) {
        // 普通订单无需特殊检查
    }
    
    @Override
    protected boolean needSpecificCheck(OrderContext context) {
        return false;
    }
}

@Service
public class GroupBuyOrderProcessor extends AbstractOrderProcessor {
    @Override
    protected void specificCheck(OrderContext context) {
        // 团购订单特殊检查
        if (!groupBuyService.isGroupValid(context.getGroupId())) {
            throw new BusinessException("团购活动已结束或人数不足");
        }
    }
    
    @Override
    protected boolean needSpecificCheck(OrderContext context) {
        return true;
    }
    
    @Autowired
    private GroupBuyService groupBuyService;
}

@Service
public class FlashSaleOrderProcessor extends AbstractOrderProcessor {
    @Override
    protected void specificCheck(OrderContext context) {
        // 秒杀订单特殊检查
        if (!flashSaleService.checkQualification(context.getUserId(), context.getFlashSaleId())) {
            throw new BusinessException("您不符合秒杀资格");
        }
    }
    
    @Override
    protected boolean needSpecificCheck(OrderContext context) {
        return true;
    }
    
    @Autowired
    private FlashSaleService flashSaleService;
}

使用工厂获取具体处理器:

java 复制代码
@Service
public class OrderProcessorFactory {
    private final Map<OrderType, AbstractOrderProcessor> processorMap;
    
    public OrderProcessorFactory(List<AbstractOrderProcessor> processors) {
        processorMap = processors.stream()
                .collect(Collectors.toMap(
                    processor -> OrderType.valueOf(processor.getClass()
                            .getSimpleName()
                            .replace("OrderProcessor", "")
                            .toUpperCase()),
                    Function.identity()
                ));
    }
    
    public AbstractOrderProcessor getProcessor(OrderType type) {
        return processorMap.get(type);
    }
}

在控制器中使用:

java 复制代码
@RestController
@RequestMapping("/orders")
public class OrderController {
    private final OrderProcessorFactory processorFactory;
    
    @PostMapping
    public OrderProcessResult createOrder(@RequestBody OrderRequest request) {
        AbstractOrderProcessor processor = processorFactory.getProcessor(request.getType());
        return processor.process(convertToContext(request));
    }
    
    private OrderContext convertToContext(OrderRequest request) {
        // 转换逻辑
    }
}

优势分析

  1. 将不变逻辑放在父类,可变逻辑放在子类,符合开闭原则
  2. 避免代码重复,公共逻辑得到复用
  3. 新增订单类型只需新增子类,不影响现有逻辑
  4. 流程控制集中在父类,便于统一管理和维护

2. 装饰器模式在API响应处理中的应用

业务场景

我们需要对API响应进行多种处理:

  1. 基础响应包装
  2. 数据脱敏(如手机号、身份证号)
  3. 数据格式转换(如日期格式)
  4. 多语言支持
  5. 响应压缩(对大响应)

这些处理可能需要灵活组合使用。

代码实现

定义响应处理器接口:

java 复制代码
public interface ResponseProcessor {
    Object process(Object response);
}

基础实现:

java 复制代码
@Service
public class BasicResponseProcessor implements ResponseProcessor {
    @Override
    public Object process(Object response) {
        if (response == null) {
            return ApiResponse.success();
        }
        return ApiResponse.success(response);
    }
}

抽象装饰器:

java 复制代码
public abstract class ResponseProcessorDecorator implements ResponseProcessor {
    protected final ResponseProcessor wrapped;
    
    public ResponseProcessorDecorator(ResponseProcessor wrapped) {
        this.wrapped = wrapped;
    }
    
    @Override
    public Object process(Object response) {
        return wrapped.process(response);
    }
}

具体装饰器实现:

java 复制代码
@Service
public class DataMaskingDecorator extends ResponseProcessorDecorator {
    public DataMaskingDecorator(ResponseProcessor wrapped) {
        super(wrapped);
    }
    
    @Override
    public Object process(Object response) {
        Object processed = super.process(response);
        return maskSensitiveData(processed);
    }
    
    private Object maskSensitiveData(Object data) {
        // 使用反射或JSON遍历实现数据脱敏
        // 例如将"13812345678"转为"138****5678"
        return data;
    }
}

@Service
public class DateFormatDecorator extends ResponseProcessorDecorator {
    public DateFormatDecorator(ResponseProcessor wrapped) {
        super(wrapped);
    }
    
    @Override
    public Object process(Object response) {
        Object processed = super.process(response);
        return formatDates(processed);
    }
    
    private Object formatDates(Object data) {
        // 统一格式化日期字段
        return data;
    }
}

@Service
public class I18nDecorator extends ResponseProcessorDecorator {
    private final MessageSource messageSource;
    
    public I18nDecorator(ResponseProcessor wrapped, MessageSource messageSource) {
        super(wrapped);
        this.messageSource = messageSource;
    }
    
    @Override
    public Object process(Object response) {
        Object processed = super.process(response);
        return translateMessages(processed);
    }
    
    private Object translateMessages(Object data) {
        // 处理多语言消息
        return data;
    }
}

使用装饰器链:

java 复制代码
@RestControllerAdvice
public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
    private final ResponseProcessor responseProcessor;
    
    public ApiResponseAdvice(
            BasicResponseProcessor basicProcessor,
            DataMaskingDecorator maskingDecorator,
            DateFormatDecorator dateFormatDecorator,
            I18nDecorator i18nDecorator) {
        // 构建装饰器链
        this.responseProcessor = i18nDecorator;
        ((I18nDecorator) this.responseProcessor).setWrapped(dateFormatDecorator);
        ((DateFormatDecorator) dateFormatDecorator).setWrapped(maskingDecorator);
        ((DataMaskingDecorator) maskingDecorator).setWrapped(basicProcessor);
    }
    
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, 
            MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, 
            ServerHttpRequest request, ServerHttpResponse response) {
        return responseProcessor.process(body);
    }
}

优势分析

  1. 可以动态添加或移除功能,比继承更灵活
  2. 每个装饰器只关注一个功能,符合单一职责原则
  3. 装饰顺序可以灵活调整,满足不同场景需求
  4. 运行时组合功能,而非编译时确定

总结

模板方法模式和装饰器模式在Spring Boot项目中有着独特的价值:

  1. ​模板方法模式​适用于有固定流程但某些步骤需要不同实现的场景,如订单处理、工作流引擎等
  2. ​装饰器模式​适用于需要动态添加功能的场景,如API响应处理、IO流处理等

这两种模式都能帮助我们构建更灵活、更易维护的系统架构。在实际项目中,我们应该根据具体业务场景选择合适的设计模式,而不是为了使用模式而使用模式。

相关推荐
崎岖Qiu1 小时前
【JVM篇11】:分代回收与GC回收范围的分类详解
java·jvm·后端·面试
许苑向上3 小时前
Spring Boot 自动装配底层源码实现详解
java·spring boot·后端
超级小忍6 小时前
深入浅出:在 Spring Boot 中构建实时应用 - 全面掌握 WebSocket
spring boot·后端·websocket
没有bug.的程序员6 小时前
《Spring Security源码深度剖析:Filter链与权限控制模型》
java·后端·spring·security·filter·权限控制
无责任此方_修行中7 小时前
不止是 AI 热潮:AWS 2025 技术峰会带给我的思考
后端·架构·aws
lang201509287 小时前
Apache Ignite 与 Spring Boot 集成
spring boot·后端·apache·ignite
Asthenia04127 小时前
深入剖析 Spring Boot 请求处理链路与 Servlet 的本质
后端
旧时光巷7 小时前
【Flask 基础 ①】 | 路由、参数与模板渲染
后端·python·零基础·flask·web·模板渲染·路由系统
小醉你真好7 小时前
Spring Boot 数据源配置中为什么可以不用写 driver-class-name
spring boot·后端·源代码管理
SirLancelot17 小时前
数据结构-Set集合(一)Set集合介绍、优缺点
java·开发语言·数据结构·后端·算法·哈希算法·set