引言
作为Java高级开发者,我经常需要在Spring Boot项目中应用设计模式来解决复杂的业务问题。今天我将分享工厂模式和观察者模式在电商系统中的实际应用,这些模式比常见的责任链和策略模式更有趣且实用。
1. 工厂模式在支付系统中的应用
在电商系统中,我们经常需要对接多种支付渠道(支付宝、微信支付、银联等),工厂模式非常适合这种场景。
业务场景
我们需要根据用户选择的支付方式创建不同的支付处理器,每种支付方式有不同的验证、处理和通知逻辑。
代码实现
首先定义支付接口:
java
public interface PaymentService {
PaymentResponse pay(PaymentRequest request);
boolean supports(PaymentType type);
}
然后实现具体的支付服务:
java
@Service
@RequiredArgsConstructor
public class AlipayService implements PaymentService {
private final AlipayConfig config;
@Override
public PaymentResponse pay(PaymentRequest request) {
// 支付宝特定的支付逻辑
return new PaymentResponse("ALIPAY_SUCCESS", "支付宝支付成功");
}
@Override
public boolean supports(PaymentType type) {
return PaymentType.ALIPAY == type;
}
}
@Service
@RequiredArgsConstructor
public class WechatPayService implements PaymentService {
private final WechatConfig config;
@Override
public PaymentResponse pay(PaymentRequest request) {
// 微信支付特定的支付逻辑
return new PaymentResponse("WECHAT_SUCCESS", "微信支付成功");
}
@Override
public boolean supports(PaymentType type) {
return PaymentType.WECHAT == type;
}
}
创建支付工厂:
java
@Service
@RequiredArgsConstructor
public class PaymentServiceFactory {
private final List<PaymentService> paymentServices;
public PaymentService getPaymentService(PaymentType type) {
return paymentServices.stream()
.filter(service -> service.supports(type))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("不支持的支付类型"));
}
}
在控制器中使用:
java
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/payment")
public class PaymentController {
private final PaymentServiceFactory paymentServiceFactory;
@PostMapping
public PaymentResponse pay(@RequestBody PaymentRequest request) {
PaymentService paymentService = paymentServiceFactory.getPaymentService(request.getType());
return paymentService.pay(request);
}
}
优势分析
- 新增支付方式只需添加新的PaymentService实现,无需修改现有代码
- 支付逻辑与创建逻辑分离,符合单一职责原则
- Spring自动收集所有PaymentService实现,工厂类简洁高效
2. 观察者模式在订单状态变更中的应用
电商系统中,订单状态变更时需要触发多种操作(发送通知、更新库存、记录日志等),观察者模式非常适合这种一对多的依赖关系。
业务场景
当订单状态发生变化时,需要:
- 发送短信/邮件通知用户
- 更新库存(如果是取消订单)
- 记录操作日志
- 触发可能的促销活动结算
代码实现
定义订单事件:
java
public class OrderEvent {
private final Order order;
private final OrderStatus oldStatus;
private final OrderStatus newStatus;
private final LocalDateTime eventTime;
// 构造器、getter省略
}
定义事件发布者:
java
@Service
@RequiredArgsConstructor
public class OrderEventPublisher {
private final ApplicationEventPublisher eventPublisher;
public void publishOrderStatusChange(Order order, OrderStatus oldStatus, OrderStatus newStatus) {
OrderEvent event = new OrderEvent(order, oldStatus, newStatus, LocalDateTime.now());
eventPublisher.publishEvent(event);
}
}
实现观察者(使用Spring的事件机制):
java
@Component
@RequiredArgsConstructor
public class OrderNotificationListener {
private final NotificationService notificationService;
@EventListener
@Async
public void handleOrderEvent(OrderEvent event) {
if (event.getNewStatus() == OrderStatus.PAID) {
notificationService.sendPaymentSuccessNotification(event.getOrder());
} else if (event.getNewStatus() == OrderStatus.SHIPPED) {
notificationService.sendShippingNotification(event.getOrder());
}
// 其他状态处理...
}
}
@Component
@RequiredArgsConstructor
public class InventoryUpdateListener {
private final InventoryService inventoryService;
@EventListener
@Async
public void handleOrderCancellation(OrderEvent event) {
if (event.getNewStatus() == OrderStatus.CANCELLED &&
event.getOldStatus() == OrderStatus.PAID) {
// 恢复库存
inventoryService.restoreInventory(event.getOrder().getItems());
}
}
}
@Component
@RequiredArgsConstructor
public class OrderLogListener {
private final OrderLogService logService;
@EventListener
public void logOrderStatusChange(OrderEvent event) {
logService.logStatusChange(
event.getOrder().getId(),
event.getOldStatus(),
event.getNewStatus(),
event.getEventTime()
);
}
}
在订单服务中使用:
java
@Service
@RequiredArgsConstructor
@Transactional
public class OrderService {
private final OrderRepository orderRepository;
private final OrderEventPublisher eventPublisher;
public void updateOrderStatus(Long orderId, OrderStatus newStatus) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
OrderStatus oldStatus = order.getStatus();
order.setStatus(newStatus);
orderRepository.save(order);
// 发布状态变更事件
eventPublisher.publishOrderStatusChange(order, oldStatus, newStatus);
}
}
优势分析
- 订单服务不需要知道有哪些组件关心状态变更,解耦明显
- 新增观察者只需添加新的监听器,不影响现有逻辑
- 使用Spring的@Async可以实现异步处理,提高响应速度
- 各观察者之间互不影响,可以独立演进
总结
工厂模式和观察者模式在Spring Boot项目中有着广泛的应用场景:
- 工厂模式特别适合需要根据不同条件创建不同实现类的场景,如支付系统、文件解析器等
- 观察者模式非常适合事件驱动的场景,如订单状态变更、用户注册等需要触发多种后续操作的业务
这两种模式都能显著提高代码的可维护性和扩展性,是Spring Boot开发者工具箱中的重要组成部分。在实际项目中,我们应该根据业务场景灵活选择和应用这些模式,而不是生搬硬套。