B.10.01.5-电商系统的设计模式应用实战


title: "设计模式实战宝典:设计模式的工程化应用"

subtitle: "从理论到实践,掌握设计模式在现代软件开发中的核心应用"
date: "2024-12-09"
category: "代码内功修炼"
tags: ["设计模式", "面向对象", "代码重构", "最佳实践"]
description: "深入解析GoF 常见设计模式在实际项目中的应用场景,提供完整的代码示例和最佳实践指南"

🎯 业务场景:电商系统的设计模式应用实战

背景挑战

假如你正在开发一个大型电商系统,面临以下典型问题:

  • 订单处理流程复杂:不同类型订单(普通订单、秒杀订单、预售订单)处理逻辑各异
  • 支付方式多样化:支持支付宝、微信、银行卡等多种支付方式,且需要支持新增
  • 商品展示策略:不同用户群体看到的商品信息和价格策略不同
  • 系统扩展性要求:需要支持快速添加新功能,不影响现有代码

量化指标

  • 支持 15+ 种不同的订单类型
  • 集成 4+ 种支付方式
  • 服务 100万+ 日活用户

🔍 技术分析:设计模式分类与选择策略

设计模式三大类别

一、创建型模式 - "如何造东西"

想象一下你要开一家工厂,专门生产各种东西。创建型模式就是教你如何设计这家工厂,让它能高效、灵活地生产出你需要的产品。
核心思想 :把"创建对象"这件事本身,也当成一个"业务逻辑"来设计,而不是直接 new 一个对象。

模式名称 一句话理解 生活中的例子 电商系统实例
单例模式 保证全世界只有一个 一个国家只有一个总统;一个班级只有一个班主任。 系统配置管理器(所有地方用的都是同一份配置);数据库连接池(避免创建过多连接浪费资源)。
工厂方法模式 子类决定造什么 我开了一家"饮料总厂"(抽象工厂),但具体是生产可乐还是矿泉水,我让"可乐分厂"和"矿泉水分厂"(具体工厂)自己去决定。 创建支付方式:有一个 PaymentFactory,但具体创建 Alipay 还是 WechatPay,由它的子类 AlipayFactoryWechatPayFactory 来实现。
抽象工厂模式 生产一整套"家族"产品 我开了一家"家具店"(抽象工厂),你跟我说要"北欧风"的,我就给你一整套北欧风的桌椅沙发(产品族);你要"中式风"的,我就给你一整套中式的。 创建不同平台的UI组件:一个 UIFactoryWindowsUIFactory 生产 Windows 风格的按钮和文本框;MacUIFactory 生产 Mac 风格的按钮和文本框。
建造者模式 分步骤组装一个复杂产品 买电脑:你先选CPU,再选内存,再选硬盘,最后组装成一台完整的电脑。而不是一次性买一台固定的。 构建一个复杂的订单:一个 OrderBuilder,你可以一步步设置 setItems(), setShippingAddress(), setPaymentInfo(),最后调用 build() 得到一个完整的订单对象。

二、结构型模式 - "如何搭积木"

现在你有了很多零件(类),结构型模式就是教你如何把这些零件巧妙地组合在一起,搭出更酷、更强大的东西。
核心思想:关注类和对象的组合,而不是它们的创建。

模式名称 一句话理解 生活中的例子 电商系统实例
适配器模式 转接头 你的耳机是3.5mm圆孔的,但手机是Type-C的,你需要一个"Type-C转3.5mm"的转接头。 你的系统需要对接一个第三方的支付接口,但它的接口方法名和你的系统不匹配,你写一个 ThirdPartyPaymentAdapter 来"翻译"一下。
装饰器模式 穿衣服 你是一个人(原始对象),你可以穿外套(增加保暖功能),戴帽子(增加防晒功能),这些"衣服"动态地给你增加了新功能,但你还是你。 计算商品价格:原始价格是100元,你可以用"折扣装饰器"打个折,再用"优惠券装饰器"减10元,最终得到最终价格。
外观模式 总开关/一键启动 你开车,只需要拧钥匙(启动),但背后是引擎、电路、油路等几十个复杂子系统协同工作。外观模式就是那个"钥匙"。 提交订单:用户点击"提交订单"按钮,背后需要检查库存、锁定库存、创建支付单、扣减优惠券等。你提供一个 OrderServiceFacade,内部调用所有这些复杂服务,对外只暴露一个简单的 submitOrder() 方法。
代理模式 找中介/替身 你想买明星的签名照,你不会直接去找明星,而是找他的经纪人(代理)。经纪人可以帮你过滤掉一些不重要的请求,或者安排时间。 为服务增加缓存:你有一个 ProductService,你创建一个 ProductServiceProxy,它和原服务有一样的方法。在调用原服务前,代理先查缓存,有就直接返回,没有再调用原服务并把结果存入缓存。

三、行为型模式 - "如何让东西动起来"

现在你的积木搭好了,行为型模式就是教这些积木之间如何"沟通"和"协作",来完成一个复杂的任务。
核心思想:关注对象之间的职责分配和算法。

模式名称 一句话理解 生活中的例子 电商系统实例
策略模式 换个方法做同一件事 你要去旅游,可以选择"坐飞机"(快但贵)、"坐高铁"(平衡)、"坐大巴"(慢但便宜)。目的地(目标)是一样的,但策略(方法)不同。 计算运费:根据用户选择的"顺丰"、"京东"、"三通一达"等不同物流策略,调用不同的计价算法来计算运费。
观察者模式 订阅通知 你关注了某个UP主(被观察者),他一发布新视频(状态改变),你就会收到通知(观察者被更新)。 订单状态变更:订单(被观察者)状态从"待支付"变为"已支付"时,系统会通知库存服务(观察者)减库存,通知物流服务(观察者)准备发货,通知用户(观察者)发送短信。
命令模式 把请求变成"命令对象" 你在餐厅点餐,服务员把你的要求写在一张订单上(命令对象),然后交给厨房。这张订单可以被"执行"(做菜),也可以被"撤销"(不要了)。 订单操作:用户的所有操作(创建订单、取消订单、申请退款)都被封装成一个个 Command 对象。系统可以把这些命令对象存起来,实现撤销或重做功能。
状态模式 状态一变,行为就变 一个自动售货机,在"无币"状态下按按钮没反应;在"有币"状态下按按钮才会出货。它的行为完全由它的内部状态决定。 订单状态机:订单在"待支付"状态下,用户行为是"去支付";在"已支付"状态下,用户行为是"申请退款";在"已发货"状态下,用户行为是"确认收货"。不同状态下,允许的操作完全不同。

🏗️ 架构设计:核心模式深度实战

1. 策略模式:价格计算引擎

业务场景

电商系统需要支持多种价格计算策略:会员折扣、满减优惠、限时秒杀等。
PriceCalculator -PriceStrategy strategy +setStrategy(PriceStrategy) +calculatePrice(Product, User) <<interface>> PriceStrategy +calculate(Product, User) MemberDiscountStrategy +calculate(Product, User) FullReductionStrategy +calculate(Product, User) SeckillStrategy +calculate(Product, User)

核心实现

java 复制代码
// 价格策略接口
public interface PriceStrategy {
    BigDecimal calculate(Product product, User user);
    String getStrategyName();
}

// 会员折扣策略
@Component("memberDiscountStrategy")
public class MemberDiscountStrategy implements PriceStrategy {
    
    @Override
    public BigDecimal calculate(Product product, User user) {
        BigDecimal originalPrice = product.getPrice();
        
        // 根据会员等级计算折扣
        BigDecimal discount = switch (user.getMemberLevel()) {
            case GOLD -> new BigDecimal("0.85");      // 8.5折
            case SILVER -> new BigDecimal("0.90");    // 9折
            case BRONZE -> new BigDecimal("0.95");    // 9.5折
            default -> BigDecimal.ONE;                // 无折扣
        };
        
        return originalPrice.multiply(discount).setScale(2, RoundingMode.HALF_UP);
    }
    
    @Override
    public String getStrategyName() {
        return "会员折扣";
    }
}

// 满减策略
@Component("fullReductionStrategy")
public class FullReductionStrategy implements PriceStrategy {
    
    @Override
    public BigDecimal calculate(Product product, User user) {
        BigDecimal originalPrice = product.getPrice();
        
        // 满100减10,满200减25,满500减60
        if (originalPrice.compareTo(new BigDecimal("500")) >= 0) {
            return originalPrice.subtract(new BigDecimal("60"));
        } else if (originalPrice.compareTo(new BigDecimal("200")) >= 0) {
            return originalPrice.subtract(new BigDecimal("25"));
        } else if (originalPrice.compareTo(new BigDecimal("100")) >= 0) {
            return originalPrice.subtract(new BigDecimal("10"));
        }
        
        return originalPrice;
    }
    
    @Override
    public String getStrategyName() {
        return "满减优惠";
    }
}

// 价格计算器
@Service
public class PriceCalculator {
    
    private final Map<String, PriceStrategy> strategies;
    
    public PriceCalculator(Map<String, PriceStrategy> strategies) {
        this.strategies = strategies;
    }
    
    public BigDecimal calculatePrice(Product product, User user, String strategyType) {
        PriceStrategy strategy = strategies.get(strategyType);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的价格策略: " + strategyType);
        }
        
        return strategy.calculate(product, user);
    }
    
    // 获取最优价格(比较所有策略)
    public PriceResult getBestPrice(Product product, User user) {
        BigDecimal bestPrice = product.getPrice();
        String bestStrategy = "原价";
        
        for (PriceStrategy strategy : strategies.values()) {
            BigDecimal price = strategy.calculate(product, user);
            if (price.compareTo(bestPrice) < 0) {
                bestPrice = price;
                bestStrategy = strategy.getStrategyName();
            }
        }
        
        return new PriceResult(bestPrice, bestStrategy);
    }
}

2. 工厂方法模式:支付方式创建

业务场景

系统需要支持多种支付方式,且要能够灵活添加新的支付方式。

java 复制代码
// 支付接口
public interface PaymentProcessor {
    PaymentResult process(PaymentRequest request);
    String getPaymentType();
    boolean isAvailable();
}

// 支付宝实现
@Component
public class AlipayProcessor implements PaymentProcessor {
    
    @Override
    public PaymentResult process(PaymentRequest request) {
        // 调用支付宝API
        log.info("处理支付宝支付,订单号:{}, 金额:{}", 
                request.getOrderId(), request.getAmount());
        
        // 模拟支付处理
        boolean success = callAlipayAPI(request);
        
        return PaymentResult.builder()
                .success(success)
                .transactionId(generateTransactionId())
                .paymentType("ALIPAY")
                .build();
    }
    
    @Override
    public String getPaymentType() {
        return "ALIPAY";
    }
    
    @Override
    public boolean isAvailable() {
        // 检查支付宝服务是否可用
        return checkAlipayService();
    }
    
    private boolean callAlipayAPI(PaymentRequest request) {
        // 实际的支付宝API调用逻辑
        return true; // 简化处理
    }
    
    private boolean checkAlipayService() {
        // 健康检查逻辑
        return true;
    }
    
    private String generateTransactionId() {
        return "ALI_" + System.currentTimeMillis();
    }
}

// 微信支付实现
@Component
public class WechatPayProcessor implements PaymentProcessor {
    
    @Override
    public PaymentResult process(PaymentRequest request) {
        log.info("处理微信支付,订单号:{}, 金额:{}", 
                request.getOrderId(), request.getAmount());
        
        boolean success = callWechatAPI(request);
        
        return PaymentResult.builder()
                .success(success)
                .transactionId(generateTransactionId())
                .paymentType("WECHAT")
                .build();
    }
    
    @Override
    public String getPaymentType() {
        return "WECHAT";
    }
    
    @Override
    public boolean isAvailable() {
        return checkWechatService();
    }
    
    private boolean callWechatAPI(PaymentRequest request) {
        return true; // 简化处理
    }
    
    private boolean checkWechatService() {
        return true;
    }
    
    private String generateTransactionId() {
        return "WX_" + System.currentTimeMillis();
    }
}

// 支付工厂
@Service
public class PaymentProcessorFactory {
    
    private final Map<String, PaymentProcessor> processors;
    
    public PaymentProcessorFactory(List<PaymentProcessor> processorList) {
        this.processors = processorList.stream()
                .collect(Collectors.toMap(
                    PaymentProcessor::getPaymentType,
                    Function.identity()
                ));
    }
    
    public PaymentProcessor createProcessor(String paymentType) {
        PaymentProcessor processor = processors.get(paymentType.toUpperCase());
        
        if (processor == null) {
            throw new UnsupportedPaymentTypeException("不支持的支付方式: " + paymentType);
        }
        
        if (!processor.isAvailable()) {
            throw new PaymentServiceUnavailableException("支付服务暂不可用: " + paymentType);
        }
        
        return processor;
    }
    
    public List<String> getAvailablePaymentTypes() {
        return processors.values().stream()
                .filter(PaymentProcessor::isAvailable)
                .map(PaymentProcessor::getPaymentType)
                .collect(Collectors.toList());
    }
}

3. 观察者模式:订单状态变更通知

业务场景

当订单状态发生变更时,需要通知多个相关系统:库存系统、物流系统、用户通知等。

java 复制代码
// 订单事件
@Data
@Builder
public class OrderEvent {
    private String orderId;
    private OrderStatus oldStatus;
    private OrderStatus newStatus;
    private LocalDateTime timestamp;
    private String userId;
    private Map<String, Object> metadata;
}

// 订单事件监听器接口
public interface OrderEventListener {
    void onOrderStatusChanged(OrderEvent event);
    String getListenerName();
    boolean isEnabled();
}

// 库存更新监听器
@Component
@Slf4j
public class InventoryUpdateListener implements OrderEventListener {
    
    @Autowired
    private InventoryService inventoryService;
    
    @Override
    public void onOrderStatusChanged(OrderEvent event) {
        if (event.getNewStatus() == OrderStatus.PAID) {
            // 订单支付成功,扣减库存
            log.info("订单支付成功,扣减库存:{}", event.getOrderId());
            inventoryService.deductInventory(event.getOrderId());
            
        } else if (event.getNewStatus() == OrderStatus.CANCELLED) {
            // 订单取消,恢复库存
            log.info("订单取消,恢复库存:{}", event.getOrderId());
            inventoryService.restoreInventory(event.getOrderId());
        }
    }
    
    @Override
    public String getListenerName() {
        return "库存更新监听器";
    }
    
    @Override
    public boolean isEnabled() {
        return true;
    }
}

// 用户通知监听器
@Component
@Slf4j
public class UserNotificationListener implements OrderEventListener {
    
    @Autowired
    private NotificationService notificationService;
    
    @Override
    public void onOrderStatusChanged(OrderEvent event) {
        String message = buildNotificationMessage(event);
        
        // 发送通知
        notificationService.sendNotification(
            event.getUserId(), 
            "订单状态更新", 
            message
        );
        
        log.info("已发送订单状态通知给用户:{}", event.getUserId());
    }
    
    private String buildNotificationMessage(OrderEvent event) {
        return switch (event.getNewStatus()) {
            case PAID -> "您的订单已支付成功,我们将尽快为您发货";
            case SHIPPED -> "您的订单已发货,请注意查收";
            case DELIVERED -> "您的订单已送达,感谢您的购买";
            case CANCELLED -> "您的订单已取消,如有疑问请联系客服";
            default -> "您的订单状态已更新";
        };
    }
    
    @Override
    public String getListenerName() {
        return "用户通知监听器";
    }
    
    @Override
    public boolean isEnabled() {
        return true;
    }
}

// 订单事件发布器
@Service
@Slf4j
public class OrderEventPublisher {
    
    private final List<OrderEventListener> listeners;
    private final ExecutorService executorService;
    
    public OrderEventPublisher(List<OrderEventListener> listeners) {
        this.listeners = listeners.stream()
                .filter(OrderEventListener::isEnabled)
                .collect(Collectors.toList());
        
        // 异步处理事件,避免阻塞主流程
        this.executorService = Executors.newFixedThreadPool(5, 
            new ThreadFactoryBuilder()
                .setNameFormat("order-event-%d")
                .setDaemon(true)
                .build());
    }
    
    public void publishOrderStatusChanged(String orderId, OrderStatus oldStatus, 
                                        OrderStatus newStatus, String userId) {
        OrderEvent event = OrderEvent.builder()
                .orderId(orderId)
                .oldStatus(oldStatus)
                .newStatus(newStatus)
                .userId(userId)
                .timestamp(LocalDateTime.now())
                .build();
        
        log.info("发布订单状态变更事件:{} {} -> {}", orderId, oldStatus, newStatus);
        
        // 异步通知所有监听器
        for (OrderEventListener listener : li
        steners) {
            executorService.submit(() -> {
                try {
                    listener.onOrderStatusChanged(event);
                } catch (Exception e) {
                    log.error("订单事件处理失败,监听器:{},订单:{}", 
                            listener.getListenerName(), orderId, e);
                }
            });
        }
    }
    
    @PreDestroy
    public void shutdown() {
        executorService.shutdown();
    }
}

4. 建造者模式:复杂订单构建

业务场景

电商订单包含商品信息、用户信息、优惠信息、配送信息等复杂结构,需要分步构建。

java 复制代码
// 订单实体
@Data
@Builder
public class Order {
    private String orderId;
    private String userId;
    private List<OrderItem> items;
    private Address shippingAddress;
    private PaymentInfo paymentInfo;
    private List<Discount> discounts;
    private BigDecimal totalAmount;
    private BigDecimal discountAmount;
    private BigDecimal finalAmount;
    private OrderStatus status;
    private LocalDateTime createTime;
    private String remark;
}

// 订单建造者
public class OrderBuilder {
    private String orderId;
    private String userId;
    private List<OrderItem> items = new ArrayList<>();
    private Address shippingAddress;
    private PaymentInfo paymentInfo;
    private List<Discount> discounts = new ArrayList<>();
    private String remark;
    
    public static OrderBuilder newOrder() {
        return new OrderBuilder();
    }
    
    public OrderBuilder orderId(String orderId) {
        this.orderId = orderId;
        return this;
    }
    
    public OrderBuilder forUser(String userId) {
        this.userId = userId;
        return this;
    }
    
    public OrderBuilder addItem(String productId, int quantity, BigDecimal price) {
        OrderItem item = OrderItem.builder()
                .productId(productId)
                .quantity(quantity)
                .unitPrice(price)
                .totalPrice(price.multiply(BigDecimal.valueOf(quantity)))
                .build();
        this.items.add(item);
        return this;
    }
    
    public OrderBuilder addItems(List<OrderItem> items) {
        this.items.addAll(items);
        return this;
    }
    
    public OrderBuilder shippingTo(Address address) {
        this.shippingAddress = address;
        return this;
    }
    
    public OrderBuilder payWith(PaymentInfo paymentInfo) {
        this.paymentInfo = paymentInfo;
        return this;
    }
    
    public OrderBuilder applyDiscount(Discount discount) {
        this.discounts.add(discount);
        return this;
    }
    
    public OrderBuilder withRemark(String remark) {
        this.remark = remark;
        return this;
    }
    
    public Order build() {
        // 验证必要字段
        validateRequiredFields();
        
        // 计算金额
        AmountCalculation calculation = calculateAmounts();
        
        return Order.builder()
                .orderId(orderId)
                .userId(userId)
                .items(new ArrayList<>(items))
                .shippingAddress(shippingAddress)
                .paymentInfo(paymentInfo)
                .discounts(new ArrayList<>(discounts))
                .totalAmount(calculation.totalAmount)
                .discountAmount(calculation.discountAmount)
                .finalAmount(calculation.finalAmount)
                .status(OrderStatus.PENDING)
                .createTime(LocalDateTime.now())
                .remark(remark)
                .build();
    }
    
    private void validateRequiredFields() {
        if (StringUtils.isBlank(orderId)) {
            throw new IllegalStateException("订单ID不能为空");
        }
        if (StringUtils.isBlank(userId)) {
            throw new IllegalStateException("用户ID不能为空");
        }
        if (items.isEmpty()) {
            throw new IllegalStateException("订单商品不能为空");
        }
        if (shippingAddress == null) {
            throw new IllegalStateException("收货地址不能为空");
        }
    }
    
    private AmountCalculation calculateAmounts() {
        // 计算商品总金额
        BigDecimal totalAmount = items.stream()
                .map(OrderItem::getTotalPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 计算折扣金额
        BigDecimal discountAmount = discounts.stream()
                .map(discount -> discount.calculateDiscount(totalAmount))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 计算最终金额
        BigDecimal finalAmount = totalAmount.subtract(discountAmount);
        if (finalAmount.compareTo(BigDecimal.ZERO) < 0) {
            finalAmount = BigDecimal.ZERO;
        }
        
        return new AmountCalculation(totalAmount, discountAmount, finalAmount);
    }
    
    private static class AmountCalculation {
        final BigDecimal totalAmount;
        final BigDecimal discountAmount;
        final BigDecimal finalAmount;
        
        AmountCalculation(BigDecimal totalAmount, BigDecimal discountAmount, BigDecimal finalAmount) {
            this.totalAmount = totalAmount;
            this.discountAmount = discountAmount;
            this.finalAmount = finalAmount;
        }
    }
}

// 使用示例
@Service
public class OrderService {
    
    public Order createOrder(CreateOrderRequest request) {
        return OrderBuilder.newOrder()
                .orderId(generateOrderId())
                .forUser(request.getUserId())
                .addItems(request.getItems())
                .shippingTo(request.getShippingAddress())
                .payWith(request.getPaymentInfo())
                .applyDiscount(request.getCoupon())
                .withRemark(request.getRemark())
                .build();
    }
    
    private String generateOrderId() {
        return "ORD_" + System.currentTimeMillis();
    }
}

🛠️ 代码实现:模式组合应用

综合案例:电商促销系统

将多个设计模式组合使用,构建一个完整的促销系统。

java 复制代码
// 促销活动管理器(外观模式 + 策略模式 + 工厂模式)
@Service
@Slf4j
public class PromotionManager {
    
    private final PromotionStrategyFactory strategyFactory;
    private final PromotionEventPublisher eventPublisher;
    private final PromotionRuleEngine ruleEngine;
    
    public PromotionManager(PromotionStrategyFactory strategyFactory,
                          PromotionEventPublisher eventPublisher,
                          PromotionRuleEngine ruleEngine) {
        this.strategyFactory = strategyFactory;
        this.eventPublisher = eventPublisher;
        this.ruleEngine = ruleEngine;
    }
    
    /**
     * 应用促销活动(外观模式:简化复杂的促销逻辑)
     */
    public PromotionResult applyPromotion(PromotionRequest request) {
        try {
            // 1. 规则引擎验证
            ValidationResult validation = ruleEngine.validate(request);
            if (!validation.isValid()) {
                return PromotionResult.failed(validation.getErrorMessage());
            }
            
            // 2. 获取促销策略(工厂模式)
            PromotionStrategy strategy = strategyFactory.getStrategy(request.getPromotionType());
            
            // 3. 执行促销计算(策略模式)
            PromotionCalculation calculation = strategy.calculate(request);
            
            // 4. 构建结果
            PromotionResult result = PromotionResult.builder()
                    .success(true)
                    .originalAmount(request.getOriginalAmount())
                    .discountAmount(calculation.getDiscountAmount())
                    .finalAmount(calculation.getFinalAmount())
                    .promotionDetails(calculation.getDetails())
                    .build();
            
            // 5. 发布事件(观察者模式)
            eventPublisher.publishPromotionApplied(request, result);
            
            log.info("促销应用成功:用户={}, 类型={}, 优惠金额={}", 
                    request.getUserId(), request.getPromotionType(), 
                    calculation.getDiscountAmount());
            
            return result;
            
        } catch (Exception e) {
            log.error("促销应用失败:{}", request, e);
            return PromotionResult.failed("促销应用失败:" + e.getMessage());
        }
    }
    
    /**
     * 获取用户可用的促销活动
     */
    public List<AvailablePromotion> getAvailablePromotions(String userId) {
        return strategyFactory.getAllStrategies().stream()
                .filter(strategy -> strategy.isApplicableForUser(userId))
                .map(strategy -> AvailablePromotion.builder()
                        .type(strategy.getPromotionType())
                        .name(strategy.getPromotionName())
                        .description(strategy.getDescription())
                        .conditions(strategy.getConditions())
                        .build())
                .collect(Collectors.toList());
    }
}

// 促销策略工厂(工厂模式 + 策略模式)
@Component
public class PromotionStrategyFactory {
    
    private final Map<String, PromotionStrategy> strategies;
    
    public PromotionStrategyFactory(List<PromotionStrategy> strategyList) {
        this.strategies = strategyList.stream()
                .collect(Collectors.toMap(
                    PromotionStrategy::getPromotionType,
                    Function.identity()
                ));
        
        log.info("初始化促销策略工厂,支持策略:{}", strategies.keySet());
    }
    
    public PromotionStrategy getStrategy(String promotionType) {
        PromotionStrategy strategy = strategies.get(promotionType);
        if (strategy == null) {
            throw new UnsupportedPromotionTypeException("不支持的促销类型:" + promotionType);
        }
        return strategy;
    }
    
    public Collection<PromotionStrategy> getAllStrategies() {
        return strategies.values();
    }
}

// 满减促销策略实现
@Component
public class FullReductionPromotionStrategy implements PromotionStrategy {
    
    @Override
    public String getPromotionType() {
        return "FULL_REDUCTION";
    }
    
    @Override
    public String getPromotionName() {
        return "满减优惠";
    }
    
    @Override
    public String getDescription() {
        return "满指定金额减指定金额";
    }
    
    @Override
    public PromotionCalculation calculate(PromotionRequest request) {
        BigDecimal originalAmount = request.getOriginalAmount();
        Map<String, Object> params = request.getPromotionParams();
        
        BigDecimal threshold = new BigDecimal(params.get("threshold").toString());
        BigDecimal reduction = new BigDecimal(params.get("reduction").toString());
        
        BigDecimal discountAmount = BigDecimal.ZERO;
        String details = "";
        
        if (originalAmount.compareTo(threshold) >= 0) {
            // 计算可以享受几次满减
            int times = originalAmount.divide(threshold, 0, RoundingMode.DOWN).intValue();
            discountAmount = reduction.multiply(BigDecimal.valueOf(times));
            details = String.format("满%s减%s,享受%d次优惠", threshold, reduction, times);
        } else {
            details = String.format("未达到满%s的条件", threshold);
        }
        
        BigDecimal finalAmount = originalAmount.subtract(discountAmount);
        
        return PromotionCalculation.builder()
                .discountAmount(discountAmount)
                .finalAmount(finalAmount)
                .details(details)
                .build();
    }
    
    @Override
    public boolean isApplicableForUser(String userId) {
        // 检查用户是否符合满减条件(如会员等级、历史消费等)
        return true; // 简化实现
    }
    
    @Override
    public List<String> getConditions() {
        return Arrays.asList("订单金额达到指定门槛", "限制使用次数");
    }
}

// 折扣促销策略实现
@Component
public class DiscountPromotionStrategy implements PromotionStrategy {
    
    @Override
    public String getPromotionType() {
        return "DISCOUNT";
    }
    
    @Override
    public String getPromotionName() {
        return "折扣优惠";
    }
    
    @Override
    public String getDescription() {
        return "按比例折扣优惠";
    }
    
    @Override
    public PromotionCalculation calculate(PromotionRequest request) {
        BigDecimal originalAmount = request.getOriginalAmount();
        Map<String, Object> params = request.getPromotionParams();
        
        BigDecimal discountRate = new BigDecimal(params.get("discountRate").toString());
        BigDecimal discountAmount = originalAmount.multiply(BigDecimal.ONE.subtract(discountRate));
        BigDecimal finalAmount = originalAmount.subtract(discountAmount);
        
        String details = String.format("享受%.1f折优惠", discountRate.multiply(BigDecimal.TEN));
        
        return PromotionCalculation.builder()
                .discountAmount(discountAmount)
                .finalAmount(finalAmount)
                .details(details)
                .build();
    }
    
    @Override
    public boolean isApplicableForUser(String userId) {
        return true; // 简化实现
    }
    
    @Override
    public List<String> getConditions() {
        return Arrays.asList("会员专享", "限时优惠");
    }
}

各模式应用频率统计

25% 20% 15% 12% 10% 8% 10% 设计模式使用频率分布 策略模式 工厂模式 观察者模式 建造者模式 装饰器模式 适配器模式 其他模式

踩坑经验总结

坑1:过度设计

问题描述:为了使用设计模式而使用,导致简单问题复杂化

java 复制代码
// ❌ 错误示例:简单的字符串拼接使用建造者模式
public class MessageBuilder {
    private StringBuilder sb = new StringBuilder();
    
    public MessageBuilder addPrefix(String prefix) {
        sb.append(prefix);
        return this;
    }
    
    public MessageBuilder addContent(String content) {
        sb.append(content);
        return this;
    }
    
    public String build() {
        return sb.toString();
    }
}

// ✅ 正确做法:直接使用字符串拼接
String message = prefix + content;

解决方案

  • 遵循KISS原则(Keep It Simple, Stupid)
  • 只在真正需要扩展性和灵活性时使用设计模式
  • 先写简单实现,在需要时再重构

坑2:模式选择错误

问题描述:场景分析不准确,选择了不合适的设计模式

java 复制代码
// ❌ 错误示例:用单例模式管理用户会话
@Component
public class UserSessionManager {
    private static UserSessionManager instance;
    private Map<String, UserSession> sessions = new ConcurrentHashMap<>();
    
    public static UserSessionManager getInstance() {
        if (instance == null) {
            synchronized (UserSessionManager.class) {
                if (instance == null) {
                    instance = new UserSessionManager();
                }
            }
        }
        return instance;
    }
    
    // 问题:单例在分布式环境下无法共享状态
}

// ✅ 正确做法:使用Redis等外部存储
@Service
public class UserSessionService {
    @Autowired
    private RedisTemplate<String, UserSession> redisTemplate;
    
    public void saveSession(String sessionId, UserSession session) {
        redisTemplate.opsForValue().set("session:" + sessionId, session, Duration.ofHours(2));
    }
}

坑3:忽略线程安全

问题描述:在多线程环境下使用设计模式时忽略线程安全问题

java 复制代码
// ❌ 错误示例:非线程安全的单例
public class ConfigManager {
    private static ConfigManager instance;
    private Properties config;
    
    public static ConfigManager getInstance() {
        if (instance == null) {  // 线程不安全
            instance = new ConfigManager();
        }
        return instance;
    }
}

// ✅ 正确做法:使用枚举实现线程安全的单例
public enum ConfigManager {
    INSTANCE;
    
    private Properties config;
    
    ConfigManager() {
        config = loadConfig();
    }
    
    public String getProperty(String key) {
        return config.getProperty(key);
    }
}

最佳实践指南

1. 模式选择决策树

是 否 是 否 是 否 是 是 否 是 否 是 是 否 是 否 是 需要创建对象? 对象创建复杂? 需要组合对象? 建造者模式 需要延迟创建? 工厂模式 需要全局唯一? 单例模式 需要统一接口? 需要算法切换? 外观模式 需要动态扩展? 装饰器模式 策略模式 需要状态管理? 状态模式 需要解耦通信? 观察者模式

🎯 总结:从理论到实践的完整路径

记住:设计模式是解决问题的工具,而不是炫技的手段。好的代码应该是简洁、清晰、可维护的,设计模式只是帮助我们达到这个目标的手段之一。

相关推荐
用户84913717547163 小时前
JustAuth实战系列(第5期):建造者模式进阶 - AuthRequestBuilder设计解析
java·设计模式·架构
希望_睿智6 小时前
实战设计模式之代理模式
c++·设计模式·架构
Freedom风间1 天前
前端必学-完美组件封装原则
前端·javascript·设计模式
王彬泽1 天前
【设计模式】代理模式
设计模式·代理模式
过客随尘1 天前
EventBus设计
设计模式
易元1 天前
模式组合应用-适配器模式
设计模式
程序视点2 天前
设计模式之原型模式!附Java代码示例!
java·后端·设计模式
玄妙尽在颠倒间2 天前
设计模式——模板模式
设计模式
极光雨雨2 天前
【设计模式】模板方法模式
设计模式·模板方法模式