我将分享两种不太常见但非常实用的设计模式在Spring Boot项目中的实际应用:模板方法模式和装饰器模式。这些模式在电商系统中能优雅地解决一些特定问题。
1. 模板方法模式在订单处理流程中的应用
业务场景
电商系统中,不同类型的订单(普通订单、团购订单、秒杀订单)有相似的处理流程,但某些步骤的实现细节不同。例如:
- 所有订单都需要验证、计算价格、扣减库存、创建支付
- 但团购订单需要额外验证成团状态
- 秒杀订单需要验证秒杀资格
代码实现
定义订单处理的抽象模板:
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) {
// 转换逻辑
}
}
优势分析
- 将不变逻辑放在父类,可变逻辑放在子类,符合开闭原则
- 避免代码重复,公共逻辑得到复用
- 新增订单类型只需新增子类,不影响现有逻辑
- 流程控制集中在父类,便于统一管理和维护
2. 装饰器模式在API响应处理中的应用
业务场景
我们需要对API响应进行多种处理:
- 基础响应包装
- 数据脱敏(如手机号、身份证号)
- 数据格式转换(如日期格式)
- 多语言支持
- 响应压缩(对大响应)
这些处理可能需要灵活组合使用。
代码实现
定义响应处理器接口:
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);
}
}
优势分析
- 可以动态添加或移除功能,比继承更灵活
- 每个装饰器只关注一个功能,符合单一职责原则
- 装饰顺序可以灵活调整,满足不同场景需求
- 运行时组合功能,而非编译时确定
总结
模板方法模式和装饰器模式在Spring Boot项目中有着独特的价值:
- 模板方法模式适用于有固定流程但某些步骤需要不同实现的场景,如订单处理、工作流引擎等
- 装饰器模式适用于需要动态添加功能的场景,如API响应处理、IO流处理等
这两种模式都能帮助我们构建更灵活、更易维护的系统架构。在实际项目中,我们应该根据具体业务场景选择合适的设计模式,而不是为了使用模式而使用模式。