设计模式是软件开发中解决特定问题的经验总结。在SpringBoot框架中,设计模式被巧妙地融入各个环节,不仅提高了框架的灵活性和扩展性,还为开发者提供了优雅的解决方案。
本文将介绍13种设计模式在SpringBoot中的实际应用,每个模式都配有具体的代码实现和应用场景。
1. 单例模式 (Singleton Pattern)
模式概述
单例模式确保一个类只有一个实例,并提供一个全局访问点。
SpringBoot应用
SpringBoot中的Bean默认都是单例的,由Spring容器负责创建和管理,保证全局唯一性。
实现示例
@Service
public class UserService {
// 构造方法私有化防止外部直接创建实例
private UserService() {
System.out.println("UserService实例被创建");
}
// Bean的作用域默认为singleton
@Autowired
private UserRepository userRepository;
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
}
@RestController
public class UserController {
// 注入的是同一个UserService实例
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
应用优势
- 减少内存占用,避免重复创建对象
- 便于管理共享资源
- 简化对象跟踪和引用
2. 工厂方法模式 (Factory Method Pattern)
模式概述
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。
SpringBoot应用
SpringBoot中的BeanFactory就是典型的工厂方法模式应用,它负责创建和管理Bean实例。
实现示例
// 支付处理器接口
public interface PaymentProcessor {
void processPayment(double amount);
}
// 具体实现 - 信用卡支付
@Component("creditCard")
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing credit card payment of $" + amount);
}
}
// 具体实现 - PayPal支付
@Component("paypal")
public class PayPalProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing PayPal payment of $" + amount);
}
}
// 支付处理器工厂
@Component
public class PaymentProcessorFactory {
@Autowired
private 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 {
@Autowired
private PaymentProcessorFactory processorFactory;
public void placeOrder(String paymentType, double amount) {
PaymentProcessor processor = processorFactory.getProcessor(paymentType);
processor.processPayment(amount);
// 处理订单其余部分...
}
}
应用优势
- 松耦合,客户端与具体实现分离
- 符合开闭原则,可以方便地添加新的支付方式
- 封装对象创建逻辑,统一管理
3. 抽象工厂模式 (Abstract Factory Pattern)
模式概述
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
SpringBoot应用
SpringBoot中的多环境配置和数据源创建就是抽象工厂模式的应用。
实现示例
// 抽象产品 - 连接
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 {
@Override
public Connection createConnection() {
return new MySQLConnection();
}
@Override
public Transaction createTransaction() {
return new MySQLTransaction();
}
}
// 具体工厂 - PostgreSQL
@Component("postgresFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "postgres")
public class PostgresDatabaseFactory implements DatabaseFactory {
@Override
public Connection createConnection() {
return new PostgresConnection();
}
@Override
public Transaction createTransaction() {
return new PostgresTransaction();
}
}
// 具体产品实现 - MySQL连接
public class MySQLConnection implements Connection {
@Override
public void connect() {
System.out.println("Connecting to MySQL database");
}
@Override
public void executeQuery(String query) {
System.out.println("Executing query on MySQL: " + query);
}
@Override
public void close() {
System.out.println("Closing MySQL connection");
}
}
// 使用抽象工厂
@Service
public class QueryService {
private final DatabaseFactory databaseFactory;
@Autowired
public 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设计中大量使用了建造者模式。
实现示例
// 产品类
@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就是原型模式的应用,每次获取都会创建新的实例。
实现示例
// 支持克隆的配置类
@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";
}
@Override
public 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
@Autowired
private ReportConfiguration defaultConfig;
// 存储预定义的模板
private Map<String, ReportConfiguration> templates = new HashMap<>();
@PostConstruct
public 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 {
@Autowired
private 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框架和第三方集成中。
实现示例
// 旧的支付服务接口
public interface LegacyPaymentService {
boolean processPayment(String accountNumber, double amount, String currency);
String getTransactionStatus(String transactionId);
}
// 旧的支付服务实现
@Service("legacyPaymentService")
public class LegacyPaymentServiceImpl implements LegacyPaymentService {
@Override
public boolean processPayment(String accountNumber, double amount, String currency) {
System.out.println("Processing payment using legacy system");
// 旧系统的支付处理逻辑
return true;
}
@Override
public 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;
@Autowired
public LegacyPaymentAdapter(LegacyPaymentService legacyService) {
this.legacyService = legacyService;
}
@Override
public 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;
}
@Override
public 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;
@Autowired
public 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等注解就是装饰器模式的应用,对原有方法进行增强。
实现示例
// 基础接口
public interface NotificationService {
void send(String message, String recipient);
}
// 基础实现
@Service
@Primary
public class EmailNotificationService implements NotificationService {
@Override
public 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);
}
@Override
public 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;
}
@Override
public 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);
}
@Override
public 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 {
@Bean
public NotificationService loggingNotificationDecorator(
@Qualifier("emailNotificationService") NotificationService emailService) {
return new LoggingNotificationDecorator(emailService);
}
@Bean
public NotificationService retryNotificationDecorator(
@Qualifier("loggingNotificationDecorator") NotificationService loggingDecorator,
@Value("${notification.max-retries:3}") int maxRetries) {
return new RetryNotificationDecorator(loggingDecorator, maxRetries);
}
@Bean
public NotificationService encryptionNotificationDecorator(
@Qualifier("retryNotificationDecorator") NotificationService retryDecorator) {
return new EncryptionNotificationDecorator(retryDecorator);
}
@Bean
@Primary
public NotificationService notificationService(
@Qualifier("encryptionNotificationDecorator") NotificationService encryptionDecorator) {
return encryptionDecorator;
}
}
// 使用装饰后的服务
@Service
public class UserService {
private final NotificationService notificationService;
@Autowired
public 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。
实现示例
// 自定义事件
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;
@Autowired
public UserRegistrationService(
ApplicationEventPublisher eventPublisher,
UserRepository userRepository) {
this.eventPublisher = eventPublisher;
this.userRepository = userRepository;
}
@Transactional
public 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;
@Autowired
public WelcomeEmailListener(EmailService emailService) {
this.emailService = emailService;
}
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 发送欢迎邮件
emailService.sendWelcomeEmail(user);
}
}
// 事件监听器 - 创建用户资料
@Component
public class UserProfileInitializer implements ApplicationListener<UserRegisteredEvent> {
private final ProfileService profileService;
@Autowired
public UserProfileInitializer(ProfileService profileService) {
this.profileService = profileService;
}
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 创建用户资料
profileService.createInitialProfile(user);
}
}
// 使用注解方式的事件监听器
@Component
public class MarketingSubscriptionHandler {
private final MarketingService marketingService;
@Autowired
public MarketingSubscriptionHandler(MarketingService marketingService) {
this.marketingService = marketingService;
}
@EventListener
@Async
public void handleUserRegistered(UserRegisteredEvent event) {
User user = event.getUser();
// 添加到营销列表
marketingService.addUserToDefaultNewsletters(user);
}
}
// 异步事件配置
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public 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;
@Override
public BigDecimal applyDiscount(BigDecimal amount, User user) {
BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage)
.divide(BigDecimal.valueOf(100));
BigDecimal discount = amount.multiply(discountFactor);
return amount.subtract(discount);
}
@Override
public 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;
@Override
public BigDecimal applyDiscount(BigDecimal amount, User user) {
BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage)
.divide(BigDecimal.valueOf(100));
BigDecimal discount = amount.multiply(discountFactor);
return amount.subtract(discount);
}
@Override
public 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;
@Override
public BigDecimal applyDiscount(BigDecimal amount, User user) {
BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage)
.divide(BigDecimal.valueOf(100));
BigDecimal discount = amount.multiply(discountFactor);
return amount.subtract(discount);
}
@Override
public boolean isApplicable(User user, ShoppingCart cart) {
return cart.getTotalAmount().compareTo(threshold) >= 0;
}
}
// 策略上下文
@Service
public class DiscountService {
private final List<DiscountStrategy> discountStrategies;
@Autowired
public 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 {
@Autowired
private ReportRepository reportRepository;
@Override
protected ReportData fetchData(ReportRequest request) {
// 从数据库获取报表数据
List<ReportRecord> records = reportRepository.findByDateRange(
request.getStartDate(), request.getEndDate());
return new ReportData(records, request.getStartDate(), request.getEndDate());
}
@Override
protected 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());
}
@Override
protected 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 {
@Autowired
private ReportRepository reportRepository;
@Override
protected ReportData fetchData(ReportRequest request) {
// 从数据库获取报表数据
List<ReportRecord> records = reportRepository.findByDateRange(
request.getStartDate(), request.getEndDate());
return new ReportData(records, request.getStartDate(), request.getEndDate());
}
@Override
protected 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 {
@Override
public 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 {
@Autowired
private FraudDetectionService fraudService;
@Override
public 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 {
@Autowired
private PaymentGateway paymentGateway;
@Override
public 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 {
@Autowired
private NotificationService notificationService;
@Override
public 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 {
@Bean
public 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;
@Autowired
public 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;
}
@Override
public void execute() {
createdOrder = orderService.createOrder(orderToCreate);
}
@Override
public void undo() {
if (createdOrder != null) {
orderRepository.delete(createdOrder);
createdOrder = null;
}
}
@Override
public 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;
}
@Override
public void execute() {
inventoryService.deductStock(productId, quantity);
executed = true;
}
@Override
public void undo() {
if (executed) {
inventoryService.addStock(productId, quantity);
executed = false;
}
}
@Override
public 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;
}
@Override
public void execute() {
PaymentResponse response = paymentService.processPayment(paymentRequest);
if (!response.isSuccess()) {
throw new PaymentFailedException(response.getMessage());
}
this.transactionId = response.getTransactionId();
}
@Override
public void undo() {
if (transactionId != null) {
paymentService.refundPayment(transactionId);
transactionId = null;
}
}
@Override
public 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;
@Autowired
public 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;
@Autowired
public 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 {
@Autowired
private ConfirmedOrderState confirmedOrderState;
@Autowired
private CancelledOrderState cancelledOrderState;
@Override
public OrderState confirm(Order order) {
// 执行确认逻辑
order.setConfirmedAt(LocalDateTime.now());
return confirmedOrderState;
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("Cannot pay for an order that has not been confirmed");
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("Cannot ship an order that has not been confirmed and paid");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("Cannot deliver an order that has not been shipped");
}
@Override
public OrderState cancel(Order order) {
// 执行取消逻辑
order.setCancelledAt(LocalDateTime.now());
order.setCancellationReason("Cancelled by customer before confirmation");
return cancelledOrderState;
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("Cannot refund an order that has not been paid");
}
@Override
public String getStatus() {
return "NEW";
}
}
// 具体状态 - 已确认
@Component
public class ConfirmedOrderState implements OrderState {
@Autowired
private PaidOrderState paidOrderState;
@Autowired
private CancelledOrderState cancelledOrderState;
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("Order is already confirmed");
}
@Override
public OrderState pay(Order order) {
// 执行支付逻辑
order.setPaidAt(LocalDateTime.now());
return paidOrderState;
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("Cannot ship an order that has not been paid");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("Cannot deliver an order that has not been shipped");
}
@Override
public OrderState cancel(Order order) {
// 执行取消逻辑
order.setCancelledAt(LocalDateTime.now());
order.setCancellationReason("Cancelled by customer after confirmation");
return cancelledOrderState;
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("Cannot refund an order that has not been paid");
}
@Override
public String getStatus() {
return "CONFIRMED";
}
}
// 具体状态 - 已支付
@Component
public class PaidOrderState implements OrderState {
@Autowired
private ShippedOrderState shippedOrderState;
@Autowired
private RefundedOrderState refundedOrderState;
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("Order is already confirmed");
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("Order is already paid");
}
@Override
public OrderState ship(Order order) {
// 执行发货逻辑
order.setShippedAt(LocalDateTime.now());
return shippedOrderState;
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("Cannot deliver an order that has not been shipped");
}
@Override
public OrderState cancel(Order order) {
throw new IllegalStateException("Cannot cancel an order that has been paid, please request a refund");
}
@Override
public OrderState refund(Order order) {
// 执行退款逻辑
order.setRefundedAt(LocalDateTime.now());
return refundedOrderState;
}
@Override
public 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;
@Transient
private OrderState currentState;
@Column(name = "status")
private String status = "NEW";
@PostLoad
private 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 {
@Autowired
private OrderRepository orderRepository;
@Autowired
private NewOrderState initialState;
@Transactional
public 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);
}
@Transactional
public Order confirmOrder(Long orderId) {
Order order = findOrderById(orderId);
order.confirm();
return orderRepository.save(order);
}
@Transactional
public Order payOrder(Long orderId) {
Order order = findOrderById(orderId);
order.pay();
return orderRepository.save(order);
}
@Transactional
public Order shipOrder(Long orderId) {
Order order = findOrderById(orderId);
order.ship();
return orderRepository.save(order);
}
@Transactional
public Order deliverOrder(Long orderId) {
Order order = findOrderById(orderId);
order.deliver();
return orderRepository.save(order);
}
@Transactional
public Order cancelOrder(Long orderId) {
Order order = findOrderById(orderId);
order.cancel();
return orderRepository.save(order);
}
@Transactional
public 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;
@Override
public 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);
}
}
应用优势
- 封装状态相关行为,使代码更加清晰
- 新增状态只需要添加新类,不需要修改现有代码
- 消除条件判断语句
- 显式地表达状态转换规则
总结
在实际开发中,这些设计模式往往不是孤立使用的,而是相互配合,共同解决复杂的业务问题。掌握这些设计模式及其应用场景,能够帮助开发者设计出更加灵活、可维护、可扩展的应用。
最后,设计模式是工具而非目的,应根据实际问题选择合适的模式,避免过度设计。合理运用设计模式,才能真正提升代码质量和开发效率。