title: "设计模式实战宝典:设计模式的工程化应用"
subtitle: "从理论到实践,掌握设计模式在现代软件开发中的核心应用"
date: "2024-12-09"
category: "代码内功修炼"
tags: ["设计模式", "面向对象", "代码重构", "最佳实践"]
description: "深入解析GoF 常见设计模式在实际项目中的应用场景,提供完整的代码示例和最佳实践指南"
🎯 业务场景:电商系统的设计模式应用实战
背景挑战
假如你正在开发一个大型电商系统,面临以下典型问题:
- 订单处理流程复杂:不同类型订单(普通订单、秒杀订单、预售订单)处理逻辑各异
- 支付方式多样化:支持支付宝、微信、银行卡等多种支付方式,且需要支持新增
- 商品展示策略:不同用户群体看到的商品信息和价格策略不同
- 系统扩展性要求:需要支持快速添加新功能,不影响现有代码
量化指标:
- 支持 15+ 种不同的订单类型
- 集成 4+ 种支付方式
- 服务 100万+ 日活用户
🔍 技术分析:设计模式分类与选择策略
设计模式三大类别
一、创建型模式 - "如何造东西"
想象一下你要开一家工厂,专门生产各种东西。创建型模式就是教你如何设计这家工厂,让它能高效、灵活地生产出你需要的产品。
核心思想 :把"创建对象"这件事本身,也当成一个"业务逻辑"来设计,而不是直接 new
一个对象。
模式名称 | 一句话理解 | 生活中的例子 | 电商系统实例 |
---|---|---|---|
单例模式 | 保证全世界只有一个 | 一个国家只有一个总统;一个班级只有一个班主任。 | 系统配置管理器(所有地方用的都是同一份配置);数据库连接池(避免创建过多连接浪费资源)。 |
工厂方法模式 | 子类决定造什么 | 我开了一家"饮料总厂"(抽象工厂),但具体是生产可乐还是矿泉水,我让"可乐分厂"和"矿泉水分厂"(具体工厂)自己去决定。 | 创建支付方式:有一个 PaymentFactory ,但具体创建 Alipay 还是 WechatPay ,由它的子类 AlipayFactory 和 WechatPayFactory 来实现。 |
抽象工厂模式 | 生产一整套"家族"产品 | 我开了一家"家具店"(抽象工厂),你跟我说要"北欧风"的,我就给你一整套北欧风的桌椅沙发(产品族);你要"中式风"的,我就给你一整套中式的。 | 创建不同平台的UI组件:一个 UIFactory ,WindowsUIFactory 生产 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. 模式选择决策树
是 否 是 否 是 否 是 是 否 是 否 是 是 否 是 否 是 需要创建对象? 对象创建复杂? 需要组合对象? 建造者模式 需要延迟创建? 工厂模式 需要全局唯一? 单例模式 需要统一接口? 需要算法切换? 外观模式 需要动态扩展? 装饰器模式 策略模式 需要状态管理? 状态模式 需要解耦通信? 观察者模式
🎯 总结:从理论到实践的完整路径
记住:设计模式是解决问题的工具,而不是炫技的手段。好的代码应该是简洁、清晰、可维护的,设计模式只是帮助我们达到这个目标的手段之一。