深入实战工厂模式与观察者模式:工厂模式与观察者模式在电商系统中的应用

引言

作为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);
    }
}

优势分析

  1. 新增支付方式只需添加新的PaymentService实现,无需修改现有代码
  2. 支付逻辑与创建逻辑分离,符合单一职责原则
  3. Spring自动收集所有PaymentService实现,工厂类简洁高效

2. 观察者模式在订单状态变更中的应用

电商系统中,订单状态变更时需要触发多种操作(发送通知、更新库存、记录日志等),观察者模式非常适合这种一对多的依赖关系。

业务场景

当订单状态发生变化时,需要:

  1. 发送短信/邮件通知用户
  2. 更新库存(如果是取消订单)
  3. 记录操作日志
  4. 触发可能的促销活动结算

代码实现

定义订单事件:

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);
    }
}

优势分析

  1. 订单服务不需要知道有哪些组件关心状态变更,解耦明显
  2. 新增观察者只需添加新的监听器,不影响现有逻辑
  3. 使用Spring的@Async可以实现异步处理,提高响应速度
  4. 各观察者之间互不影响,可以独立演进

总结

工厂模式和观察者模式在Spring Boot项目中有着广泛的应用场景:

  1. ​工厂模式​特别适合需要根据不同条件创建不同实现类的场景,如支付系统、文件解析器等
  2. ​观察者模式​非常适合事件驱动的场景,如订单状态变更、用户注册等需要触发多种后续操作的业务

这两种模式都能显著提高代码的可维护性和扩展性,是Spring Boot开发者工具箱中的重要组成部分。在实际项目中,我们应该根据业务场景灵活选择和应用这些模式,而不是生搬硬套。

相关推荐
jgbazsh几秒前
Spring中把一个bean对象交给Spring容器管理的三种方式
java·后端·spring
华仔啊12 分钟前
前端不懂 Java?后端怕 CSS?这套AI全栈方案专治各种偏科
java·前端·后端
木易 士心12 分钟前
Node.js 后端开发全解析:从核心原理架构到实战应用
后端·架构·node.js
皮卡丘不断更13 分钟前
我把传统项目问答升级成了 Agent-RAG:Spring Boot + FastAPI + ChromaDB 工程落地实践
人工智能·spring boot·后端·架构·python3.11
H5css�海秀9 小时前
今天是自学大模型的第一天(sanjose)
后端·python·node.js·php
SuniaWang9 小时前
《Spring AI + 大模型全栈实战》学习手册系列 · 专题六:《Vue3 前端开发实战:打造企业级 RAG 问答界面》
java·前端·人工智能·spring boot·后端·spring·架构
韩立学长9 小时前
Springboot校园跑腿业务系统0b7amk02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
sheji34169 小时前
【开题答辩全过程】以 基于springboot的扶贫系统为例,包含答辩的问题和答案
java·spring boot·后端
代码栈上的思考10 小时前
消息队列:内存与磁盘数据中心设计与实现
后端·spring
程序员小假11 小时前
我们来说一下 b+ 树与 b 树的区别
java·后端