SpringBoot中13种设计模式应用案例

1. 单例模式 (Singleton Pattern)

模式概述

单例模式确保一个类只有一个实例,并提供一个全局访问点。

SpringBoot应用

SpringBoot中的Bean默认都是单例的,由Spring容器负责创建和管理,保证全局唯一性。

实现示例

@Service
public class UserService {// 构造方法私有化防止外部直接创建实例private UserService() {System.out.println("UserService实例被创建");}// Bean的作用域默认为singleton@Autowiredprivate UserRepository userRepository;public User findById(Long id) {return userRepository.findById(id).orElse(null);}
}@RestController
public class UserController {// 注入的是同一个UserService实例@Autowiredprivate UserService userService;@GetMapping("/users/{id}")public User getUser(@PathVariable Long id) {return userService.findById(id);}
}

应用优势

  • 减少内存占用,避免重复创建对象
  • 便于管理共享资源
  • 简化对象跟踪和引用

2. 工厂方法模式 (Factory Method Pattern)

模式概述

工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。

SpringBoot应用

SpringBoot中的BeanFactory就是典型的工厂方法模式应用,它负责创建和管理Bean实例。

实现示例

typescript 体验AI代码助手 代码解读复制代码// 支付处理器接口
public interface PaymentProcessor {void processPayment(double amount);
}// 具体实现 - 信用卡支付
@Component("creditCard")
public class CreditCardProcessor implements PaymentProcessor {@Overridepublic void processPayment(double amount) {System.out.println("Processing credit card payment of $" + amount);}
}// 具体实现 - PayPal支付
@Component("paypal")
public class PayPalProcessor implements PaymentProcessor {@Overridepublic void processPayment(double amount) {System.out.println("Processing PayPal payment of $" + amount);}
}// 支付处理器工厂
@Component
public class PaymentProcessorFactory {@Autowiredprivate Map<String, PaymentProcessor> processors;public PaymentProcessor getProcessor(String type) {PaymentProcessor processor = processors.get(type);if (processor == null) {throw new IllegalArgumentException("No payment processor found for type: " + type);}return processor;}
}// 使用工厂
@Service
public class OrderService {@Autowiredprivate PaymentProcessorFactory processorFactory;public void placeOrder(String paymentType, double amount) {PaymentProcessor processor = processorFactory.getProcessor(paymentType);processor.processPayment(amount);// 处理订单其余部分...}
}

应用优势

  • 松耦合,客户端与具体实现分离
  • 符合开闭原则,可以方便地添加新的支付方式
  • 封装对象创建逻辑,统一管理

3. 抽象工厂模式 (Abstract Factory Pattern)

模式概述

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

SpringBoot应用

SpringBoot中的多环境配置和数据源创建就是抽象工厂模式的应用。

实现示例

typescript 体验AI代码助手 代码解读复制代码// 抽象产品 - 连接
public interface Connection {void connect();void executeQuery(String query);void close();
}// 抽象产品 - 事务
public interface Transaction {void begin();void commit();void rollback();
}// 抽象工厂
public interface DatabaseFactory {Connection createConnection();Transaction createTransaction();
}// 具体工厂 - MySQL
@Component("mysqlFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "mysql")
public class MySQLDatabaseFactory implements DatabaseFactory {@Overridepublic Connection createConnection() {return new MySQLConnection();}@Overridepublic Transaction createTransaction() {return new MySQLTransaction();}
}// 具体工厂 - PostgreSQL
@Component("postgresFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "postgres")
public class PostgresDatabaseFactory implements DatabaseFactory {@Overridepublic Connection createConnection() {return new PostgresConnection();}@Overridepublic Transaction createTransaction() {return new PostgresTransaction();}
}// 具体产品实现 - MySQL连接
public class MySQLConnection implements Connection {@Overridepublic void connect() {System.out.println("Connecting to MySQL database");}@Overridepublic void executeQuery(String query) {System.out.println("Executing query on MySQL: " + query);}@Overridepublic void close() {System.out.println("Closing MySQL connection");}
}// 使用抽象工厂
@Service
public class QueryService {private final DatabaseFactory databaseFactory;@Autowiredpublic QueryService(@Qualifier("mysqlFactory") DatabaseFactory databaseFactory) {this.databaseFactory = databaseFactory;}public void executeQuery(String query) {Connection connection = databaseFactory.createConnection();Transaction transaction = databaseFactory.createTransaction();try {connection.connect();transaction.begin();connection.executeQuery(query);transaction.commit();} catch (Exception e) {transaction.rollback();} finally {connection.close();}}
}

应用优势

  • 提供一组相关对象而非单个对象
  • 确保创建的产品相互匹配
  • 便于环境切换(如开发、测试、生产环境)

4. 建造者模式 (Builder Pattern)

模式概述

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

SpringBoot应用

SpringBoot中的配置类和链式API设计中大量使用了建造者模式。

实现示例

typescript 体验AI代码助手 代码解读复制代码// 产品类
@Data
public class EmailMessage {private String from;private List<String> to;private List<String> cc;private String subject;private String body;private boolean html;private List<String> attachments;private LocalDateTime scheduledTime;// 私有构造器,只能通过Builder创建private EmailMessage() {}// 建造者类public static class Builder {private EmailMessage message;public Builder() {message = new EmailMessage();message.to = new ArrayList<>();message.cc = new ArrayList<>();message.attachments = new ArrayList<>();}public Builder from(String from) {message.from = from;return this;}public Builder to(String to) {message.to.add(to);return this;}public Builder cc(String cc) {message.cc.add(cc);return this;}public Builder subject(String subject) {message.subject = subject;return this;}public Builder body(String body) {message.body = body;return this;}public Builder html(boolean html) {message.html = html;return this;}public Builder attachment(String attachment) {message.attachments.add(attachment);return this;}public Builder scheduledTime(LocalDateTime scheduledTime) {message.scheduledTime = scheduledTime;return this;}public EmailMessage build() {if (message.from == null || message.to.isEmpty() || message.subject == null) {throw new IllegalStateException("From, To and Subject are required");}return message;}}
}// 服务使用建造者模式
@Service
public class EmailService {// 使用建造者构造复杂对象public void sendWelcomeEmail(User user) {EmailMessage message = new EmailMessage.Builder().from("noreply@example.com").to(user.getEmail()).subject("Welcome to Our Platform").body("<h1>Welcome, " + user.getName() + "!</h1><p>Thanks for joining us.</p>").html(true).build();sendEmail(message);}private void sendEmail(EmailMessage message) {// 发送邮件逻辑System.out.println("Sending email: " + message);}
}

应用优势

  • 参数可控制性强,可以逐步构建对象
  • 良好的可读性,类似自然语言描述
  • 支持多种配置组合,而不需要大量重载的构造函数

5. 原型模式 (Prototype Pattern)

模式概述

原型模式通过复制现有对象而非创建新实例来创建对象,用于创建成本高昂的对象。

SpringBoot应用

SpringBoot中的bean作用域prototype就是原型模式的应用,每次获取都会创建新的实例。

实现示例

typescript 体验AI代码助手 代码解读复制代码// 支持克隆的配置类
@Component
@Scope("prototype")
public class ReportConfiguration implements Cloneable {private String reportType;private List<String> columns;private String sortBy;private boolean ascending;private String dateRange;// 默认构造器设置基础配置public ReportConfiguration() {this.reportType = "summary";this.columns = new ArrayList<>(Arrays.asList("id", "name", "date"));this.sortBy = "date";this.ascending = false;this.dateRange = "last7days";}@Overridepublic ReportConfiguration clone() {try {ReportConfiguration clone = (ReportConfiguration) super.clone();// 深复制列表clone.columns = new ArrayList<>(this.columns);return clone;} catch (CloneNotSupportedException e) {throw new RuntimeException(e);}}// getter和setter方法// ...
}// 报表工厂使用原型模式
@Service
public class ReportFactory {// 注入原型bean@Autowiredprivate ReportConfiguration defaultConfig;// 存储预定义的模板private Map<String, ReportConfiguration> templates = new HashMap<>();@PostConstructpublic void initTemplates() {// 创建财务报表模板ReportConfiguration financialTemplate = defaultConfig.clone();financialTemplate.setReportType("financial");financialTemplate.setColumns(Arrays.asList("id", "amount", "transaction_date", "category"));financialTemplate.setSortBy("amount");templates.put("financial", financialTemplate);// 创建用户活动报表模板ReportConfiguration activityTemplate = defaultConfig.clone();activityTemplate.setReportType("activity");activityTemplate.setColumns(Arrays.asList("user_id", "action", "timestamp", "ip_address"));activityTemplate.setSortBy("timestamp");templates.put("activity", activityTemplate);}// 基于已有模板创建新配置public ReportConfiguration createFromTemplate(String templateName) {ReportConfiguration template = templates.get(templateName);if (template == null) {throw new IllegalArgumentException("Template not found: " + templateName);}return template.clone();}// 基于默认配置创建新配置public ReportConfiguration createDefault() {return defaultConfig.clone();}
}// 使用原型模式
@RestController
@RequestMapping("/reports")
public class ReportController {@Autowiredprivate ReportFactory reportFactory;@GetMapping("/financial")public String generateFinancialReport(@RequestParam Map<String, String> params) {// 获取财务报表模板并自定义ReportConfiguration config = reportFactory.createFromTemplate("financial");// 根据请求参数自定义报表配置if (params.containsKey("dateRange")) {config.setDateRange(params.get("dateRange"));}// 使用配置生成报表...return "Financial report generated with config: " + config;}
}

应用优势

  • 避免反复执行初始化代码
  • 提供配置模板,方便创建预定义对象
  • 减少子类数量,通过复制实现对象变异

6. 适配器模式 (Adapter Pattern)

模式概述

适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。

SpringBoot应用

SpringBoot中的各种适配器广泛应用于MVC框架和第三方集成中。

实现示例

java 体验AI代码助手 代码解读复制代码// 旧的支付服务接口
public interface LegacyPaymentService {boolean processPayment(String accountNumber, double amount, String currency);String getTransactionStatus(String transactionId);
}// 旧的支付服务实现
@Service("legacyPaymentService")
public class LegacyPaymentServiceImpl implements LegacyPaymentService {@Overridepublic boolean processPayment(String accountNumber, double amount, String currency) {System.out.println("Processing payment using legacy system");// 旧系统的支付处理逻辑return true;}@Overridepublic String getTransactionStatus(String transactionId) {// 旧系统获取交易状态的逻辑return "COMPLETED";}
}// 新的支付接口
public interface ModernPaymentGateway {PaymentResponse pay(PaymentRequest request);TransactionStatus checkStatus(String reference);
}// 支付请求和响应模型
@Data
public class PaymentRequest {private String customerId;private BigDecimal amount;private String currencyCode;private String paymentMethod;private Map<String, String> metadata;
}@Data
public class PaymentResponse {private String referenceId;private boolean successful;private String message;
}public enum TransactionStatus {PENDING, PROCESSING, COMPLETED, FAILED, REFUNDED
}// 适配器:将旧接口适配到新接口
@Component
public class LegacyPaymentAdapter implements ModernPaymentGateway {private final LegacyPaymentService legacyService;@Autowiredpublic LegacyPaymentAdapter(LegacyPaymentService legacyService) {this.legacyService = legacyService;}@Overridepublic PaymentResponse pay(PaymentRequest request) {// 将新的请求模型转换为旧接口参数boolean result = legacyService.processPayment(request.getCustomerId(),request.getAmount().doubleValue(),request.getCurrencyCode());// 将旧接口结果转换为新的响应模型PaymentResponse response = new PaymentResponse();response.setSuccessful(result);response.setReferenceId(UUID.randomUUID().toString());response.setMessage(result ? "Payment processed successfully" : "Payment failed");return response;}@Overridepublic TransactionStatus checkStatus(String reference) {// 将旧接口的状态映射为新接口的枚举String status = legacyService.getTransactionStatus(reference);switch (status) {case "COMPLETED":return TransactionStatus.COMPLETED;case "FAILED":return TransactionStatus.FAILED;case "IN_PROGRESS":return TransactionStatus.PROCESSING;default:return TransactionStatus.PENDING;}}
}// 使用新接口
@Service
public class CheckoutService {private final ModernPaymentGateway paymentGateway;@Autowiredpublic CheckoutService(ModernPaymentGateway paymentGateway) {this.paymentGateway = paymentGateway;}public void processCheckout(Cart cart, String customerId) {// 创建支付请求PaymentRequest request = new PaymentRequest();request.setCustomerId(customerId);request.setAmount(cart.getTotal());request.setCurrencyCode("USD");// 使用适配后的接口处理支付PaymentResponse response = paymentGateway.pay(request);if (response.isSuccessful()) {// 处理成功逻辑} else {// 处理失败逻辑}}
}

应用优势

  • 复用现有代码,避免重写
  • 平滑过渡,新旧系统并行运行
  • 分离客户代码和接口实现

7. 装饰器模式 (Decorator Pattern)

模式概述

装饰器模式动态地给一个对象添加一些额外的职责,相比生成子类更为灵活。

SpringBoot应用

SpringBoot中的@Cacheable等注解就是装饰器模式的应用,对原有方法进行增强。

实现示例

java 体验AI代码助手 代码解读复制代码// 基础接口
public interface NotificationService {void send(String message, String recipient);
}// 基础实现
@Service
@Primary
public class EmailNotificationService implements NotificationService {@Overridepublic void send(String message, String recipient) {System.out.println("Sending email to " + recipient + ": " + message);// 实际发送邮件的逻辑}
}// 装饰器基类
public abstract class NotificationDecorator implements NotificationService {protected NotificationService wrapped;public NotificationDecorator(NotificationService wrapped) {this.wrapped = wrapped;}
}// 日志装饰器
@Component
public class LoggingNotificationDecorator extends NotificationDecorator {private final Logger logger = LoggerFactory.getLogger(LoggingNotificationDecorator.class);public LoggingNotificationDecorator(NotificationService wrapped) {super(wrapped);}@Overridepublic void send(String message, String recipient) {logger.info("Sending notification to: {}", recipient);long startTime = System.currentTimeMillis();wrapped.send(message, recipient);long endTime = System.currentTimeMillis();logger.info("Notification sent in {}ms", (endTime - startTime));}
}// 重试装饰器
@Component
public class RetryNotificationDecorator extends NotificationDecorator {private final Logger logger = LoggerFactory.getLogger(RetryNotificationDecorator.class);private final int maxRetries;public RetryNotificationDecorator(@Qualifier("loggingNotificationDecorator") NotificationService wrapped, @Value("${notification.max-retries:3}") int maxRetries) {super(wrapped);this.maxRetries = maxRetries;}@Overridepublic void send(String message, String recipient) {int attempts = 0;boolean sent = false;while (!sent && attempts < maxRetries) {try {attempts++;wrapped.send(message, recipient);sent = true;} catch (Exception e) {logger.warn("Failed to send notification (attempt {}): {}", attempts, e.getMessage());if (attempts >= maxRetries) {logger.error("Max retries reached, giving up");throw e;}try {// 指数退避Thread.sleep((long) Math.pow(2, attempts) * 100);} catch (InterruptedException ie) {Thread.currentThread().interrupt();}}}}
}// 加密装饰器
@Component
public class EncryptionNotificationDecorator extends NotificationDecorator {public EncryptionNotificationDecorator(@Qualifier("retryNotificationDecorator") NotificationService wrapped) {super(wrapped);}@Overridepublic void send(String message, String recipient) {String encryptedMessage = encrypt(message);wrapped.send(encryptedMessage, recipient);}private String encrypt(String message) {// 加密逻辑return "ENCRYPTED[" + message + "]";}
}// 装饰器配置
@Configuration
public class NotificationConfig {@Beanpublic NotificationService loggingNotificationDecorator(@Qualifier("emailNotificationService") NotificationService emailService) {return new LoggingNotificationDecorator(emailService);}@Beanpublic NotificationService retryNotificationDecorator(@Qualifier("loggingNotificationDecorator") NotificationService loggingDecorator,@Value("${notification.max-retries:3}") int maxRetries) {return new RetryNotificationDecorator(loggingDecorator, maxRetries);}@Beanpublic NotificationService encryptionNotificationDecorator(@Qualifier("retryNotificationDecorator") NotificationService retryDecorator) {return new EncryptionNotificationDecorator(retryDecorator);}@Bean@Primarypublic NotificationService notificationService(@Qualifier("encryptionNotificationDecorator") NotificationService encryptionDecorator) {return encryptionDecorator;}
}// 使用装饰后的服务
@Service
public class UserService {private final NotificationService notificationService;@Autowiredpublic UserService(NotificationService notificationService) {this.notificationService = notificationService;}public void notifyUser(User user, String message) {// 这里使用的是经过多层装饰的服务:加密->重试->日志->邮件notificationService.send(message, user.getEmail());}
}

应用优势

  • 动态添加功能,保持接口一致
  • 符合开闭原则,无需修改原有代码
  • 可按需组合多种增强能力

8. 观察者模式 (Observer Pattern)

模式概述

观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

SpringBoot应用

SpringBoot中的事件机制是观察者模式的典型应用,如ApplicationEvent和ApplicationListener。

实现示例

java 体验AI代码助手 代码解读复制代码// 自定义事件
public class UserRegisteredEvent extends ApplicationEvent {private final User user;public UserRegisteredEvent(Object source, User user) {super(source);this.user = user;}public User getUser() {return user;}
}// 事件发布者
@Service
public class UserRegistrationService {private final ApplicationEventPublisher eventPublisher;private final UserRepository userRepository;@Autowiredpublic UserRegistrationService(ApplicationEventPublisher eventPublisher,UserRepository userRepository) {this.eventPublisher = eventPublisher;this.userRepository = userRepository;}@Transactionalpublic User registerUser(UserRegistrationDto registrationDto) {// 创建并保存用户User user = new User();user.setUsername(registrationDto.getUsername());user.setEmail(registrationDto.getEmail());user.setPassword(encodePassword(registrationDto.getPassword()));user.setRegistrationDate(LocalDateTime.now());User savedUser = userRepository.save(user);// 发布用户注册事件eventPublisher.publishEvent(new UserRegisteredEvent(this, savedUser));return savedUser;}private String encodePassword(String password) {// 密码加密逻辑return "{bcrypt}" + password;}
}// 事件监听器 - 发送欢迎邮件
@Component
public class WelcomeEmailListener implements ApplicationListener<UserRegisteredEvent> {private final EmailService emailService;@Autowiredpublic WelcomeEmailListener(EmailService emailService) {this.emailService = emailService;}@Overridepublic void onApplicationEvent(UserRegisteredEvent event) {User user = event.getUser();// 发送欢迎邮件emailService.sendWelcomeEmail(user);}
}// 事件监听器 - 创建用户资料
@Component
public class UserProfileInitializer implements ApplicationListener<UserRegisteredEvent> {private final ProfileService profileService;@Autowiredpublic UserProfileInitializer(ProfileService profileService) {this.profileService = profileService;}@Overridepublic void onApplicationEvent(UserRegisteredEvent event) {User user = event.getUser();// 创建用户资料profileService.createInitialProfile(user);}
}// 使用注解方式的事件监听器
@Component
public class MarketingSubscriptionHandler {private final MarketingService marketingService;@Autowiredpublic MarketingSubscriptionHandler(MarketingService marketingService) {this.marketingService = marketingService;}@EventListener@Asyncpublic void handleUserRegistered(UserRegisteredEvent event) {User user = event.getUser();// 添加到营销列表marketingService.addUserToDefaultNewsletters(user);}
}// 异步事件配置
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(25);executor.setThreadNamePrefix("EventHandler-");executor.initialize();return executor;}
}

应用优势

  • 松耦合,事件发布者无需知道谁在监听
  • 支持一对多通知
  • 可实现异步处理和事件分发
  • 便于扩展新的监听者

9. 策略模式 (Strategy Pattern)

模式概述

策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换,让算法的变化独立于使用它的客户。

SpringBoot应用

策略模式广泛用于SpringBoot中的各种可配置策略,如缓存策略、认证策略等。

实现示例

// 折扣策略接口
public interface DiscountStrategy {BigDecimal applyDiscount(BigDecimal amount, User user);boolean isApplicable(User user, ShoppingCart cart);
}// 新用户折扣策略
@Component
public class NewUserDiscountStrategy implements DiscountStrategy {@Value("${discount.new-user.percentage:10}")private int discountPercentage;@Overridepublic BigDecimal applyDiscount(BigDecimal amount, User user) {BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage).divide(BigDecimal.valueOf(100));BigDecimal discount = amount.multiply(discountFactor);return amount.subtract(discount);}@Overridepublic boolean isApplicable(User user, ShoppingCart cart) {LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);return user.getRegistrationDate().isAfter(thirtyDaysAgo);}
}// 会员折扣策略
@Component
public class PremiumMemberDiscountStrategy implements DiscountStrategy {@Value("${discount.premium-member.percentage:15}")private int discountPercentage;@Overridepublic BigDecimal applyDiscount(BigDecimal amount, User user) {BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage).divide(BigDecimal.valueOf(100));BigDecimal discount = amount.multiply(discountFactor);return amount.subtract(discount);}@Overridepublic boolean isApplicable(User user, ShoppingCart cart) {return "PREMIUM".equals(user.getMembershipLevel());}
}// 大订单折扣策略
@Component
public class LargeOrderDiscountStrategy implements DiscountStrategy {@Value("${discount.large-order.threshold:1000}")private BigDecimal threshold;@Value("${discount.large-order.percentage:5}")private int discountPercentage;@Overridepublic BigDecimal applyDiscount(BigDecimal amount, User user) {BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage).divide(BigDecimal.valueOf(100));BigDecimal discount = amount.multiply(discountFactor);return amount.subtract(discount);}@Overridepublic boolean isApplicable(User user, ShoppingCart cart) {return cart.getTotalAmount().compareTo(threshold) >= 0;}
}// 策略上下文
@Service
public class DiscountService {private final List<DiscountStrategy> discountStrategies;@Autowiredpublic DiscountService(List<DiscountStrategy> discountStrategies) {this.discountStrategies = discountStrategies;}public BigDecimal calculateDiscountedAmount(BigDecimal originalAmount, User user, ShoppingCart cart) {// 查找最佳折扣策略DiscountStrategy bestStrategy = findBestDiscountStrategy(user, cart);if (bestStrategy != null) {return bestStrategy.applyDiscount(originalAmount, user);}// 无可用折扣return originalAmount;}private DiscountStrategy findBestDiscountStrategy(User user, ShoppingCart cart) {BigDecimal originalAmount = cart.getTotalAmount();BigDecimal bestDiscount = BigDecimal.ZERO;DiscountStrategy bestStrategy = null;for (DiscountStrategy strategy : discountStrategies) {if (strategy.isApplicable(user, cart)) {BigDecimal discountedAmount = strategy.applyDiscount(originalAmount, user);BigDecimal discount = originalAmount.subtract(discountedAmount);if (discount.compareTo(bestDiscount) > 0) {bestDiscount = discount;bestStrategy = strategy;}}}return bestStrategy;}
}

应用优势

  • 算法可以独立于使用它的客户而变化
  • 消除条件判断语句
  • 易于扩展新的策略
  • 提高代码复用性

10. 模板方法模式 (Template Method Pattern)

模式概述

模板方法模式定义了一个算法的骨架,将一些步骤延迟到子类中实现,使子类可以不改变算法结构的情况下重定义算法的某些步骤。

SpringBoot应用

SpringBoot中的JdbcTemplate、RestTemplate等都是模板方法模式的应用。

实现示例

// 抽象导出处理器
@Component
public abstract class AbstractReportExporter {// 模板方法定义了算法的骨架public final void exportReport(ReportRequest request, OutputStream output) {try {// 1. 验证请求validateRequest(request);// 2. 获取数据ReportData data = fetchData(request);// 3. 处理数据ReportData processedData = processData(data);// 4. 格式化数据(由子类实现)byte[] formattedData = formatData(processedData);// 5. 写入输出流output.write(formattedData);output.flush();// 6. 记录导出操作logExport(request, processedData);} catch (Exception e) {handleExportError(e, request);}}// 默认实现的方法protected void validateRequest(ReportRequest request) {if (request == null) {throw new IllegalArgumentException("Report request cannot be null");}if (request.getStartDate() == null || request.getEndDate() == null) {throw new IllegalArgumentException("Start date and end date are required");}if (request.getStartDate().isAfter(request.getEndDate())) {throw new IllegalArgumentException("Start date cannot be after end date");}}// 抽象方法,必须由子类实现protected abstract ReportData fetchData(ReportRequest request);// 钩子方法,子类可以选择性覆盖protected ReportData processData(ReportData data) {// 默认实现:不做任何处理return data;}// 抽象方法,必须由子类实现protected abstract byte[] formatData(ReportData data) throws IOException;// 默认实现的方法protected void logExport(ReportRequest request, ReportData data) {System.out.println("Report exported for period: " + request.getStartDate() + " to " + request.getEndDate() + ", records: " + data.getRecords().size());}// 默认实现的方法protected void handleExportError(Exception e, ReportRequest request) {System.err.println("Error exporting report: " + e.getMessage());throw new ReportExportException("Failed to export report", e);}
}// PDF导出器实现
@Component("pdfExporter")
public class PdfReportExporter extends AbstractReportExporter {@Autowiredprivate ReportRepository reportRepository;@Overrideprotected ReportData fetchData(ReportRequest request) {// 从数据库获取报表数据List<ReportRecord> records = reportRepository.findByDateRange(request.getStartDate(), request.getEndDate());return new ReportData(records, request.getStartDate(), request.getEndDate());}@Overrideprotected ReportData processData(ReportData data) {// 处理数据,如排序、分组、计算统计值等List<ReportRecord> processedRecords = data.getRecords().stream().sorted(Comparator.comparing(ReportRecord::getDate)).collect(Collectors.toList());return new ReportData(processedRecords, data.getStartDate(), data.getEndDate());}@Overrideprotected byte[] formatData(ReportData data) throws IOException {Document document = new Document();ByteArrayOutputStream baos = new ByteArrayOutputStream();try {PdfWriter.getInstance(document, baos);document.open();// 添加标题document.add(new Paragraph("Report from " + data.getStartDate() + " to " + data.getEndDate()));// 创建表格PdfPTable table = new PdfPTable(3);table.addCell("Date");table.addCell("Description");table.addCell("Amount");// 添加数据行for (ReportRecord record : data.getRecords()) {table.addCell(record.getDate().toString());table.addCell(record.getDescription());table.addCell(record.getAmount().toString());}document.add(table);} finally {if (document.isOpen()) {document.close();}}return baos.toByteArray();}
}// Excel导出器实现
@Component("excelExporter")
public class ExcelReportExporter extends AbstractReportExporter {@Autowiredprivate ReportRepository reportRepository;@Overrideprotected ReportData fetchData(ReportRequest request) {// 从数据库获取报表数据List<ReportRecord> records = reportRepository.findByDateRange(request.getStartDate(), request.getEndDate());return new ReportData(records, request.getStartDate(), request.getEndDate());}@Overrideprotected byte[] formatData(ReportData data) throws IOException {Workbook workbook = new XSSFWorkbook();ByteArrayOutputStream baos = new ByteArrayOutputStream();try {Sheet sheet = workbook.createSheet("Report");// 创建标题行Row headerRow = sheet.createRow(0);headerRow.createCell(0).setCellValue("Date");headerRow.createCell(1).setCellValue("Description");headerRow.createCell(2).setCellValue("Amount");// 添加数据行int rowNum = 1;for (ReportRecord record : data.getRecords()) {Row row = sheet.createRow(rowNum++);row.createCell(0).setCellValue(record.getDate().toString());row.createCell(1).setCellValue(record.getDescription());row.createCell(2).setCellValue(record.getAmount().doubleValue());}// 调整列宽for (int i = 0; i < 3; i++) {sheet.autoSizeColumn(i);}workbook.write(baos);} finally {workbook.close();}return baos.toByteArray();}
}// 使用模板方法模式
@RestController
@RequestMapping("/reports")
public class ReportController {@Autowired@Qualifier("pdfExporter")private AbstractReportExporter pdfExporter;@Autowired@Qualifier("excelExporter")private AbstractReportExporter excelExporter;@GetMapping(value = "/export/pdf", produces = MediaType.APPLICATION_PDF_VALUE)public void exportPdf(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,HttpServletResponse response) throws IOException {response.setHeader("Content-Disposition", "attachment; filename=report.pdf");ReportRequest request = new ReportRequest();request.setStartDate(startDate);request.setEndDate(endDate);pdfExporter.exportReport(request, response.getOutputStream());}@GetMapping(value = "/export/excel", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")public void exportExcel(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,HttpServletResponse response) throws IOException {response.setHeader("Content-Disposition", "attachment; filename=report.xlsx");ReportRequest request = new ReportRequest();request.setStartDate(startDate);request.setEndDate(endDate);excelExporter.exportReport(request, response.getOutputStream());}
}

应用优势

  • 封装不变部分,扩展可变部分
  • 提取公共代码,减少重复
  • 控制子类扩展点
  • 遵循好莱坞原则:“别调用我们,我们会调用你”

11. 责任链模式 (Chain of Responsibility Pattern)

模式概述

责任链模式为请求创建了一个接收者对象的链,请求会沿着这条链传递,直到有一个对象处理它为止。

SpringBoot应用

SpringBoot中的Filter链就是责任链模式的应用,多个Filter依次处理请求。

实现示例

// 抽象处理器
public abstract class PaymentHandler {protected PaymentHandler nextHandler;public void setNext(PaymentHandler handler) {this.nextHandler = handler;}public abstract PaymentResponse handle(PaymentRequest request);
}// 验证处理器
@Component
public class ValidationHandler extends PaymentHandler {@Overridepublic PaymentResponse handle(PaymentRequest request) {// 验证支付请求if (request.getAmount().compareTo(BigDecimal.ZERO) <= 0) {return new PaymentResponse(false, "Payment amount must be greater than zero");}if (request.getCardNumber() == null || request.getCardNumber().isEmpty()) {return new PaymentResponse(false, "Card number is required");}if (request.getCardNumber().length() < 13 || request.getCardNumber().length() > 19) {return new PaymentResponse(false, "Invalid card number length");}if (request.getExpiryDate() == null) {return new PaymentResponse(false, "Expiry date is required");}if (request.getExpiryDate().isBefore(YearMonth.now())) {return new PaymentResponse(false, "Card has expired");}// 验证通过,继续下一个处理器if (nextHandler != null) {return nextHandler.handle(request);}return new PaymentResponse(true, "Validation successful");}
}// 欺诈检测处理器
@Component
public class FraudDetectionHandler extends PaymentHandler {@Autowiredprivate FraudDetectionService fraudService;@Overridepublic PaymentResponse handle(PaymentRequest request) {// 检查是否存在欺诈风险FraudCheckResult checkResult = fraudService.checkForFraud(request.getCardNumber(), request.getAmount(),request.getIpAddress());if (checkResult.isFraudulent()) {return new PaymentResponse(false, "Transaction flagged as potentially fraudulent: " + checkResult.getReason());}// 欺诈检查通过,继续下一个处理器if (nextHandler != null) {return nextHandler.handle(request);}return new PaymentResponse(true, "Fraud check passed");}
}// 支付处理器
@Component
public class PaymentProcessingHandler extends PaymentHandler {@Autowiredprivate PaymentGateway paymentGateway;@Overridepublic PaymentResponse handle(PaymentRequest request) {// 实际执行支付PaymentGatewayResponse gatewayResponse = paymentGateway.processPayment(request.getCardNumber(),request.getExpiryDate(),request.getCvv(),request.getAmount());if (!gatewayResponse.isSuccessful()) {return new PaymentResponse(false, "Payment failed: " + gatewayResponse.getMessage());}// 支付成功,继续下一个处理器if (nextHandler != null) {PaymentResponse nextResponse = nextHandler.handle(request);// 如果下一环节失败,需要进行退款if (!nextResponse.isSuccess()) {paymentGateway.refund(gatewayResponse.getTransactionId(), request.getAmount());return nextResponse;}// 添加交易ID到响应nextResponse.setTransactionId(gatewayResponse.getTransactionId());return nextResponse;}return new PaymentResponse(true, "Payment processed successfully", gatewayResponse.getTransactionId());}
}// 通知处理器
@Component
public class NotificationHandler extends PaymentHandler {@Autowiredprivate NotificationService notificationService;@Overridepublic PaymentResponse handle(PaymentRequest request) {// 发送支付成功通知notificationService.sendPaymentConfirmation(request.getEmail(),request.getAmount(),LocalDateTime.now());// 继续下一个处理器if (nextHandler != null) {return nextHandler.handle(request);}return new PaymentResponse(true, "Payment completed and notification sent");}
}// 责任链配置
@Configuration
public class PaymentHandlerConfig {@Beanpublic PaymentHandler paymentHandlerChain(ValidationHandler validationHandler,FraudDetectionHandler fraudDetectionHandler,PaymentProcessingHandler paymentProcessingHandler,NotificationHandler notificationHandler) {// 构建处理链validationHandler.setNext(fraudDetectionHandler);fraudDetectionHandler.setNext(paymentProcessingHandler);paymentProcessingHandler.setNext(notificationHandler);// 返回链的第一个处理器return validationHandler;}
}// 支付服务
@Service
public class PaymentService {private final PaymentHandler paymentHandlerChain;@Autowiredpublic PaymentService(PaymentHandler paymentHandlerChain) {this.paymentHandlerChain = paymentHandlerChain;}public PaymentResponse processPayment(PaymentRequest request) {// 启动责任链处理return paymentHandlerChain.handle(request);}
}

应用优势

  • 降低耦合度,请求发送者和接收者解耦
  • 动态组合处理器,灵活调整处理流程
  • 符合单一职责原则,每个处理器专注于一项任务
  • 易于添加新的处理器,扩展性好

12. 命令模式 (Command Pattern)

模式概述

命令模式将请求封装成对象,使发出请求的责任和执行请求的责任分割开,支持请求排队、回退等功能。

SpringBoot应用

在SpringBoot应用的事件处理、任务调度中经常使用命令模式。

实现示例

// 命令接口
public interface Command {void execute();void undo();String getDescription();
}// 具体命令 - 创建订单
@Component
public class CreateOrderCommand implements Command {private final OrderService orderService;private final OrderRepository orderRepository;private Order createdOrder;private final Order orderToCreate;public CreateOrderCommand(OrderService orderService,OrderRepository orderRepository,Order orderToCreate) {this.orderService = orderService;this.orderRepository = orderRepository;this.orderToCreate = orderToCreate;}@Overridepublic void execute() {createdOrder = orderService.createOrder(orderToCreate);}@Overridepublic void undo() {if (createdOrder != null) {orderRepository.delete(createdOrder);createdOrder = null;}}@Overridepublic String getDescription() {return "Create order for customer: " + orderToCreate.getCustomerId();}
}// 具体命令 - 扣减库存
@Component
public class DeductInventoryCommand implements Command {private final InventoryService inventoryService;private final Long productId;private final int quantity;private boolean executed = false;public DeductInventoryCommand(InventoryService inventoryService,Long productId,int quantity) {this.inventoryService = inventoryService;this.productId = productId;this.quantity = quantity;}@Overridepublic void execute() {inventoryService.deductStock(productId, quantity);executed = true;}@Overridepublic void undo() {if (executed) {inventoryService.addStock(productId, quantity);executed = false;}}@Overridepublic String getDescription() {return "Deduct " + quantity + " units from product: " + productId;}
}// 具体命令 - 处理支付
@Component
public class ProcessPaymentCommand implements Command {private final PaymentService paymentService;private final PaymentRequest paymentRequest;private String transactionId;public ProcessPaymentCommand(PaymentService paymentService,PaymentRequest paymentRequest) {this.paymentService = paymentService;this.paymentRequest = paymentRequest;}@Overridepublic void execute() {PaymentResponse response = paymentService.processPayment(paymentRequest);if (!response.isSuccess()) {throw new PaymentFailedException(response.getMessage());}this.transactionId = response.getTransactionId();}@Overridepublic void undo() {if (transactionId != null) {paymentService.refundPayment(transactionId);transactionId = null;}}@Overridepublic String getDescription() {return "Process payment of " + paymentRequest.getAmount() + " for order: " + paymentRequest.getOrderId();}
}// 命令历史记录
@Component
public class CommandHistory {private final Deque<Command> history = new ArrayDeque<>();public void push(Command command) {history.push(command);}public Command pop() {return history.isEmpty() ? null : history.pop();}public boolean isEmpty() {return history.isEmpty();}public List<Command> getExecutedCommands() {return new ArrayList<>(history);}
}// 命令执行器
@Service
public class CommandInvoker {private final CommandHistory history;private final TransactionTemplate transactionTemplate;@Autowiredpublic CommandInvoker(CommandHistory history,PlatformTransactionManager transactionManager) {this.history = history;this.transactionTemplate = new TransactionTemplate(transactionManager);}public void executeCommand(Command command) {transactionTemplate.execute(status -> {try {command.execute();history.push(command);return null;} catch (Exception e) {status.setRollbackOnly();throw e;}});}public void executeCommands(List<Command> commands) {transactionTemplate.execute(status -> {List<Command> executedCommands = new ArrayList<>();try {for (Command command : commands) {command.execute();executedCommands.add(command);}// 所有命令执行成功后添加到历史记录for (Command command : executedCommands) {history.push(command);}return null;} catch (Exception e) {// 出现异常,回滚已执行的命令for (int i = executedCommands.size() - 1; i >= 0; i--) {executedCommands.get(i).undo();}status.setRollbackOnly();throw e;}});}public void undoLastCommand() {Command command = history.pop();if (command != null) {transactionTemplate.execute(status -> {try {command.undo();return null;} catch (Exception e) {status.setRollbackOnly();// 撤销失败,将命令重新放回历史history.push(command);throw e;}});}}
}// 订单处理服务
@Service
public class OrderProcessingService {private final CommandInvoker commandInvoker;private final OrderService orderService;private final InventoryService inventoryService;private final PaymentService paymentService;@Autowiredpublic OrderProcessingService(CommandInvoker commandInvoker,OrderService orderService,InventoryService inventoryService,PaymentService paymentService) {this.commandInvoker = commandInvoker;this.orderService = orderService;this.inventoryService = inventoryService;this.paymentService = paymentService;}public Order placeOrder(OrderRequest orderRequest) {// 准备订单数据Order order = new Order();order.setCustomerId(orderRequest.getCustomerId());order.setItems(orderRequest.getItems());order.setTotalAmount(calculateTotal(orderRequest.getItems()));// 创建支付请求PaymentRequest paymentRequest = new PaymentRequest();paymentRequest.setAmount(order.getTotalAmount());paymentRequest.setCardNumber(orderRequest.getPaymentDetails().getCardNumber());paymentRequest.setExpiryDate(orderRequest.getPaymentDetails().getExpiryDate());paymentRequest.setCvv(orderRequest.getPaymentDetails().getCvv());// 创建命令列表List<Command> commands = new ArrayList<>();// 1. 创建订单命令Command createOrderCommand = new CreateOrderCommand(orderService, orderService.getRepository(), order);commands.add(createOrderCommand);// 2. 扣减库存命令for (OrderItem item : order.getItems()) {Command deductInventoryCommand = new DeductInventoryCommand(inventoryService, item.getProductId(), item.getQuantity());commands.add(deductInventoryCommand);}// 3. 处理支付命令Command processPaymentCommand = new ProcessPaymentCommand(paymentService, paymentRequest);commands.add(processPaymentCommand);// 执行命令序列commandInvoker.executeCommands(commands);return order;}private BigDecimal calculateTotal(List<OrderItem> items) {return items.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add);}
}

应用优势

  • 请求发送者和接收者解耦
  • 支持撤销操作
  • 可以组合命令实现复杂操作
  • 便于实现事务和日志

13. 状态模式 (State Pattern)

模式概述

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

SpringBoot应用

在业务流程处理、订单状态管理等场景常用状态模式。

实现示例

// 订单状态接口
public interface OrderState {OrderState confirm(Order order);OrderState pay(Order order);OrderState ship(Order order);OrderState deliver(Order order);OrderState cancel(Order order);OrderState refund(Order order);String getStatus();
}// 具体状态 - 新建
@Component
public class NewOrderState implements OrderState {@Autowiredprivate ConfirmedOrderState confirmedOrderState;@Autowiredprivate CancelledOrderState cancelledOrderState;@Overridepublic OrderState confirm(Order order) {// 执行确认逻辑order.setConfirmedAt(LocalDateTime.now());return confirmedOrderState;}@Overridepublic OrderState pay(Order order) {throw new IllegalStateException("Cannot pay for an order that has not been confirmed");}@Overridepublic OrderState ship(Order order) {throw new IllegalStateException("Cannot ship an order that has not been confirmed and paid");}@Overridepublic OrderState deliver(Order order) {throw new IllegalStateException("Cannot deliver an order that has not been shipped");}@Overridepublic OrderState cancel(Order order) {// 执行取消逻辑order.setCancelledAt(LocalDateTime.now());order.setCancellationReason("Cancelled by customer before confirmation");return cancelledOrderState;}@Overridepublic OrderState refund(Order order) {throw new IllegalStateException("Cannot refund an order that has not been paid");}@Overridepublic String getStatus() {return "NEW";}
}// 具体状态 - 已确认
@Component
public class ConfirmedOrderState implements OrderState {@Autowiredprivate PaidOrderState paidOrderState;@Autowiredprivate CancelledOrderState cancelledOrderState;@Overridepublic OrderState confirm(Order order) {throw new IllegalStateException("Order is already confirmed");}@Overridepublic OrderState pay(Order order) {// 执行支付逻辑order.setPaidAt(LocalDateTime.now());return paidOrderState;}@Overridepublic OrderState ship(Order order) {throw new IllegalStateException("Cannot ship an order that has not been paid");}@Overridepublic OrderState deliver(Order order) {throw new IllegalStateException("Cannot deliver an order that has not been shipped");}@Overridepublic OrderState cancel(Order order) {// 执行取消逻辑order.setCancelledAt(LocalDateTime.now());order.setCancellationReason("Cancelled by customer after confirmation");return cancelledOrderState;}@Overridepublic OrderState refund(Order order) {throw new IllegalStateException("Cannot refund an order that has not been paid");}@Overridepublic String getStatus() {return "CONFIRMED";}
}// 具体状态 - 已支付
@Component
public class PaidOrderState implements OrderState {@Autowiredprivate ShippedOrderState shippedOrderState;@Autowiredprivate RefundedOrderState refundedOrderState;@Overridepublic OrderState confirm(Order order) {throw new IllegalStateException("Order is already confirmed");}@Overridepublic OrderState pay(Order order) {throw new IllegalStateException("Order is already paid");}@Overridepublic OrderState ship(Order order) {// 执行发货逻辑order.setShippedAt(LocalDateTime.now());return shippedOrderState;}@Overridepublic OrderState deliver(Order order) {throw new IllegalStateException("Cannot deliver an order that has not been shipped");}@Overridepublic OrderState cancel(Order order) {throw new IllegalStateException("Cannot cancel an order that has been paid, please request a refund");}@Overridepublic OrderState refund(Order order) {// 执行退款逻辑order.setRefundedAt(LocalDateTime.now());return refundedOrderState;}@Overridepublic String getStatus() {return "PAID";}
}// 更多状态类实现...// 订单状态上下文类
@Entity
@Table(name = "orders")
@Data
public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Long customerId;@OneToMany(cascade = CascadeType.ALL)private List<OrderItem> items;private BigDecimal totalAmount;private LocalDateTime createdAt = LocalDateTime.now();private LocalDateTime confirmedAt;private LocalDateTime paidAt;private LocalDateTime shippedAt;private LocalDateTime deliveredAt;private LocalDateTime cancelledAt;private String cancellationReason;private LocalDateTime refundedAt;@Transientprivate OrderState currentState;@Column(name = "status")private String status = "NEW";@PostLoadprivate void onLoad() {initState();}private void initState() {if (status == null) {status = "NEW";}switch (status) {case "NEW":currentState = SpringContextHolder.getBean(NewOrderState.class);break;case "CONFIRMED":currentState = SpringContextHolder.getBean(ConfirmedOrderState.class);break;case "PAID":currentState = SpringContextHolder.getBean(PaidOrderState.class);break;case "SHIPPED":currentState = SpringContextHolder.getBean(ShippedOrderState.class);break;case "DELIVERED":currentState = SpringContextHolder.getBean(DeliveredOrderState.class);break;case "CANCELLED":currentState = SpringContextHolder.getBean(CancelledOrderState.class);break;case "REFUNDED":currentState = SpringContextHolder.getBean(RefundedOrderState.class);break;default:throw new IllegalStateException("Unknown order status: " + status);}}// 状态转换方法public void confirm() {currentState = currentState.confirm(this);status = currentState.getStatus();}public void pay() {currentState = currentState.pay(this);status = currentState.getStatus();}public void ship() {currentState = currentState.ship(this);status = currentState.getStatus();}public void deliver() {currentState = currentState.deliver(this);status = currentState.getStatus();}public void cancel() {currentState = currentState.cancel(this);status = currentState.getStatus();}public void refund() {currentState = currentState.refund(this);status = currentState.getStatus();}
}// 订单服务
@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate NewOrderState initialState;@Transactionalpublic Order createOrder(Long customerId, List<OrderItem> items, BigDecimal totalAmount) {Order order = new Order();order.setCustomerId(customerId);order.setItems(items);order.setTotalAmount(totalAmount);order.setCurrentState(initialState);return orderRepository.save(order);}@Transactionalpublic Order confirmOrder(Long orderId) {Order order = findOrderById(orderId);order.confirm();return orderRepository.save(order);}@Transactionalpublic Order payOrder(Long orderId) {Order order = findOrderById(orderId);order.pay();return orderRepository.save(order);}@Transactionalpublic Order shipOrder(Long orderId) {Order order = findOrderById(orderId);order.ship();return orderRepository.save(order);}@Transactionalpublic Order deliverOrder(Long orderId) {Order order = findOrderById(orderId);order.deliver();return orderRepository.save(order);}@Transactionalpublic Order cancelOrder(Long orderId) {Order order = findOrderById(orderId);order.cancel();return orderRepository.save(order);}@Transactionalpublic Order refundOrder(Long orderId) {Order order = findOrderById(orderId);order.refund();return orderRepository.save(order);}private Order findOrderById(Long orderId) {return orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("Order not found: " + orderId));}
}

SpringContext持有类(用于在实体中获取Bean)

@Component
public class SpringContextHolder implements ApplicationContextAware {private static ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {context = applicationContext;}public static <T> T getBean(Class<T> clazz) {return context.getBean(clazz);}public static Object getBean(String name) {return context.getBean(name);}
}

应用优势

  • 封装状态相关行为,使代码更加清晰
  • 新增状态只需要添加新类,不需要修改现有代码
  • 消除条件判断语句
  • 显式地表达状态转换规则