告别烂代码!SpringBoot 设计模式通关秘籍:13 招搞定复杂业务

举报
HELLO程序员 发表于 2025/12/13 13:14:36 2025/12/13
【摘要】 设计模式这玩意儿,说白了就是程序员前辈们踩坑踩出来的 “祖传经验包”—— 专门解决软件开发里那些反复出现的破问题。而在 SpringBoot 框架里,设计模式简直是 “隐身大佬”,悄咪咪藏在各个角落:既让框架变得灵活好扩展,又给咱们开发者递上了 “优雅解题剧本”,不用自己瞎琢磨重复造轮子。今天就给大家扒一扒13 种设计模式在 SpringBoot 里的实战玩法,每种模式都配了能直接跑的代码 ...

设计模式这玩意儿,说白了就是程序员前辈们踩坑踩出来的 “祖传经验包”—— 专门解决软件开发里那些反复出现的破问题。

而在 SpringBoot 框架里,设计模式简直是 “隐身大佬”,悄咪咪藏在各个角落:既让框架变得灵活好扩展,又给咱们开发者递上了 “优雅解题剧本”,不用自己瞎琢磨重复造轮子。

今天就给大家扒一扒13 种设计模式在 SpringBoot 里的实战玩法,每种模式都配了能直接跑的代码 + 真实应用场景,新手也能一看就会,老鸟看完直接封神!

1. 单例模式(Singleton Pattern)

模式概述

主打一个 “独苗政策”:确保一个类这辈子只生一个实例,还得给全局留个 “访问入口”,谁要都给同一个。

SpringBoot 实战场景

SpringBoot 里的 Bean 默认就是 “独苗”!由 Spring 容器统一创建、管理,保证全项目上下用的都是同一个对象 —— 比如你在 Controller 和 Service 里注入的 UserService,压根就是同一个 “打工人”。

代码示例(直接 CV)

@Service
public class UserService {
    // 私有构造器:防着外人随便new,主打一个“垄断”
    private UserService() {
        System.out.println("UserService实例上线打工啦~");
    }
    // Bean默认就是单例,不用额外配置
    @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);
    }
}

实战优势

省内存: 不用反复 new 对象,减少 “内存垃圾”

好管理: 共享资源(比如数据库连接)统一掌控,不混乱

易追踪: 全项目就一个实例,排查问题不用到处找

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

模式概述

相当于 “对象生产流水线”:定义一个 “造对象” 的接口,具体造哪种对象,让子类自己说了算 —— 父类只负责 “发号施令”,不插手具体 “生产”。

SpringBoot 实战场景

SpringBoot 的 BeanFactory 就是典型的 “工厂老板”!专门负责创建和管理 Bean 实例,你要啥 Bean,跟它说一声,它就给你造(或拿)一个,不用你自己 new。

代码示例(支付场景专用)

// 支付处理器接口:相当于“生产规范”
public interface PaymentProcessor {
    void processPayment(double amount);
}
// 具体实现1:信用卡支付(流水线1号)
@Component("creditCard")
public class CreditCardProcessor implements PaymentProcessor {
    @Override
    public void processPayment(double amount) {
        System.out.println("正在用信用卡支付 $" + amount + ",刷起来~");
    }
}
// 具体实现2:PayPal支付(流水线2号)
@Component("paypal")
public class PayPalProcessor implements PaymentProcessor {
    @Override
    public void processPayment(double amount) {
        System.out.println("正在用PayPal支付 $" + amount + ",境外消费走起~");
    }
}
// 支付工厂:“流水线调度中心”
@Component
public class PaymentProcessorFactory {
    // 自动注入所有PaymentProcessor实现,存成Map(key是@Component的value)
    @Autowired
    private Map<String, PaymentProcessor> processors;
    // 按需“调流水线”
    public PaymentProcessor getProcessor(String type) {
        PaymentProcessor processor = processors.get(type);
        if (processor == null) {
            throw new IllegalArgumentException("没找到[" + 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);
        // 后续订单处理...
    }
}

实战优势

解耦: 调用方(OrderService)不用知道具体是哪种支付,只管 “付钱”

易扩展: 新增支付方式(比如微信支付),只需要加个实现类,不用改旧代码(符合 “开闭原则”)

统一管理: 对象创建逻辑全放工厂里,不乱套

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

模式概述

“超级工厂” 升级版:不止造一个对象,而是造一整套 “相关联的对象家族”—— 比如造数据库,不仅造连接(Connection),还造事务(Transaction),保证一套对象 “配套能用”。

SpringBoot 实战场景

SpringBoot 的多环境配置、数据源创建,全靠它!比如开发环境用 MySQL,生产环境用 PostgreSQL,切换环境时,一套 “数据库相关对象”(连接、事务)全切换,不用改代码。

代码示例(多数据源切换)

// 抽象产品1:数据库连接
public interface Connection {
    void connect();
    void executeQuery(String query);
    void close();
}
// 抽象产品2:数据库事务
public interface Transaction {
    void begin();
    void commit();
    void rollback();
}
// 抽象工厂:定义“造一套产品”的规范
public interface DatabaseFactory {
    Connection createConnection();
    Transaction createTransaction();
}
// 具体工厂1:MySQL工厂(造MySQL的连接和事务)
@Component("mysqlFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "mysql") // 配置文件里db.type=mysql时生效
public class MySQLDatabaseFactory implements DatabaseFactory {
    @Override
    public Connection createConnection() {
        return new MySQLConnection();
    }
    @Override
    public Transaction createTransaction() {
        return new MySQLTransaction();
    }
}
// 具体工厂2:PostgreSQL工厂(造PostgreSQL的连接和事务)
@Component("postgresFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "postgres") // 配置文件里db.type=postgres时生效
public class PostgresDatabaseFactory implements DatabaseFactory {
    @Override
    public Connection createConnection() {
        return new PostgresConnection();
    }
    @Override
    public Transaction createTransaction() {
        return new PostgresTransaction();
    }
}
// 具体产品实现:MySQL连接(省略MySQLTransaction、PostgresConnection等实现)
public class MySQLConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("正在连接MySQL数据库,冲!");
    }
    @Override
    public void executeQuery(String query) {
        System.out.println("在MySQL上执行SQL:" + query);
    }
    @Override
    public void close() {
        System.out.println("关闭MySQL连接,拜拜~");
    }
}
// 使用抽象工厂
@Service
public class QueryService {
    private final DatabaseFactory databaseFactory;
    // 注入指定的工厂(比如mysqlFactory)
    @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(); // 不管成功失败,都关连接
        }
    }
}

实战优势

成套创建: 相关对象一起造,保证兼容性(比如 MySQL 连接配 MySQL 事务,不会乱配)

环境切换方便: 改个配置文件,整套数据源就切换,不用改业务代码

扩展性强: 新增数据库类型(比如 Oracle),只需要加一个具体工厂和对应的产品实现

4. 建造者模式(Builder Pattern)

模式概述

“复杂对象组装大师”:把复杂对象的 “构建过程” 和 “最终样子” 分开,同一个构建过程,能组装出不同的 “成品”—— 比如拼乐高,同样的步骤,能拼出不同的造型。

SpringBoot 实战场景

SpringBoot 的配置类、链式 API(比如 Lambda 表达式里的链式调用),全是它的身影!比如构建一个复杂的邮件对象(有收件人、抄送、附件、主题等),用建造者模式一步步组装,清晰又不易出错。

代码示例(邮件发送场景)

// 产品类:邮件对象
@Data
public class EmailMessage {
    private String from; // 发件人
    private List<String> to; // 收件人
    private List<String> cc; // 抄送
    private String subject; // 主题
    private String body; // 正文
    private boolean html; // 是否是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("发件人、收件人、主题是必填项,别偷懒!");
            }
            return message;
        }
    }
}
// 邮件服务:用建造者组装邮件
@Service
public class EmailService {
    public void sendWelcomeEmail(User user) {
        // 一步步组装邮件,像拼乐高一样简单
        EmailMessage message = new EmailMessage.Builder()
                .from("noreply@example.com")
                .to(user.getEmail())
                .subject("欢迎加入我们的平台~")
                .body("<h1>欢迎你," + user.getName() + "!</h1><p>感谢注册,一起搞事情~</p>")
                .html(true) // 支持HTML格式
                .build();
        sendEmail(message);
    }
    private void sendEmail(EmailMessage message) {
        // 发送邮件逻辑
        System.out.println("正在发送邮件:" + message);
    }
}

实战优势

参数可控: 一步步设置参数,不用记一堆构造器参数的顺序(再也不用面对new Email(from, to, cc, subject, …)的噩梦)

可读性强: 链式调用像 “说话” 一样,一看就知道在组装什么

支持多配置: 同一个 Builder,能组装出不同参数的对象(比如有的邮件有附件,有的没有)

5. 原型模式(Prototype Pattern)

模式概述

“对象复制粘贴大师”:不重新 new 对象,而是通过 “复制” 一个现有对象(原型)来创建新对象 —— 适合那些 “创建成本高” 的对象(比如初始化要查数据库、加载大量配置)。

SpringBoot 实战场景

SpringBoot 的prototype Bean scope 就是它的实现!每次注入prototype类型的 Bean,都会创建一个新实例 —— 相当于 “复制” 了原型对象,再按需修改。

代码示例(报表配置场景)

// 报表配置类(支持克隆,相当于“原型”)
@Component
@Scope("prototype") // 标记为原型Bean,每次注入都new一个新的
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("没找到[" + 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 "财务报表生成成功,配置:" + config;
    }
}

实战优势

省时间: 不用反复执行初始化逻辑(比如查数据库),复制一下就好

模板复用: 预定义模板,后续创建新对象只需 “复制 + 微调”

减少子类: 不用为了不同配置创建一堆子类,复制原型就能实现差异化

6. 适配器模式(Adapter Pattern)

模式概述

“接口翻译官”:把一个类的接口,转换成另一个接口客户端能接受的样子 —— 相当于手机充电器的转接头,Type-C 接口的充电器,用转接头就能给 iPhone 充电。

SpringBoot 实战场景

SpringBoot 的 MVC 框架、第三方接口集成,全靠它 “搭桥”!比如老系统的支付接口(参数是 accountNumber、amount),新系统要用新接口(参数是 PaymentRequest),用适配器转一下,老接口就能在新系统里用。

代码示例(新旧支付系统对接)

// 老支付系统接口( legacy = 老旧的,难用的 )
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("用老系统处理支付,别嫌慢~");
        // 老系统的支付逻辑(祖传代码,不敢改)
        return true;
    }
    @Override
    public String getTransactionStatus(String transactionId) {
        // 老系统查支付状态的逻辑
        return "COMPLETED";
    }
}
// 新支付系统接口(现代、优雅)
public interface ModernPaymentGateway {
    PaymentResponse pay(PaymentRequest request);
    TransactionStatus checkStatus(String reference);
}
// 新系统的请求/响应模型(优雅的DTO)
@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(), // 新的customerId = 老的accountNumber
                request.getAmount().doubleValue(), // 新的BigDecimal = 老的double
                request.getCurrencyCode() // 新的currencyCode = 老的currency
        );
        // 第二步:把老接口的返回值,转换成新接口的返回值
        PaymentResponse response = new PaymentResponse();
        response.setSuccessful(result);
        response.setReferenceId(UUID.randomUUID().toString());
        response.setMessage(result ? "支付成功~" : "支付失败,再试试!");
        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;
        }
    }
}
// 新系统的 checkout 服务(只用新接口,不知道老系统的存在)
@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、@Transactional注解,全是它的杰作!比如一个普通的查询方法,加个@Cacheable,就多了 “缓存” 功能;加个@Transactional,就多了 “事务” 功能 —— 原方法代码一点没改。

代码示例(通知服务增强)

// 基础接口:通知服务(核心功能:发通知)
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("给[" + recipient + "]发邮件:" + message);
        // 实际发邮件的逻辑
    }
}
// 装饰器基类:所有装饰器都要继承它(相当于“衣服的基础款”)
public abstract class NotificationDecorator implements NotificationService {
    protected NotificationService wrapped; // 被装饰的对象(比如EmailNotificationService)
    public NotificationDecorator(NotificationService wrapped) {
        this.wrapped = wrapped;
    }
}
// 装饰器1:日志装饰器(给通知加“日志记录”技能)
@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("准备给[" + recipient + "]发通知啦~");
        long startTime = System.currentTimeMillis();
        wrapped.send(message, recipient); // 调用被装饰对象的核心功能
        long endTime = System.currentTimeMillis();
        logger.info("给[" + recipient + "]发通知完成,耗时[" + (endTime - startTime) + "]ms");
    }
}
// 装饰器2:重试装饰器(给通知加“失败重试”技能)
@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("第[" + attempts + "]次发通知失败:" + e.getMessage());
                if (attempts >= maxRetries) {
                    logger.error("重试次数用完了,发通知彻底失败!");
                    throw e;
                }
                // 指数退避:重试间隔越来越长(100ms、200ms、400ms...)
                try {
                    Thread.sleep((long) Math.pow(2, attempts) * 100);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
// 装饰器3:加密装饰器(给通知加“消息加密”技能)
@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:装饰器链的最外层(加密装饰器)
    @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; // Spring提供的事件发布器
    private final UserRepository userRepository;
    @Autowired
    public UserRegistrationService(
            ApplicationEventPublisher eventPublisher,
            UserRepository userRepository) {
        this.eventPublisher = eventPublisher;
        this.userRepository = userRepository;
    }
    @Transactional
    public User registerUser(UserRegistrationDto registrationDto) {
        // 1. 创建并保存用户(核心业务)
        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);
        // 2. 发布“用户注册成功”事件(发推文)
        eventPublisher.publishEvent(new UserRegisteredEvent(this, savedUser));
        return savedUser;
    }
    private String encodePassword(String password) {
        // 密码加密逻辑(比如BCrypt)
        return "{bcrypt}" + password;
    }
}
// 事件监听器1:发送欢迎邮件(听众1)
@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);
    }
}
// 事件监听器2:创建用户档案(听众2)
@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);
    }
}
// 事件监听器3:添加营销订阅(听众3,用注解方式,更简洁)
@Component
public class MarketingSubscriptionHandler {
    private final MarketingService marketingService;
    @Autowired
    public MarketingSubscriptionHandler(MarketingService marketingService) {
        this.marketingService = marketingService;
    }
    // @EventListener:标记为事件监听器,监听UserRegisteredEvent
    // @Async:异步执行,不阻塞主线程
    @EventListener
    @Async
    public void handleUserRegistered(UserRegisteredEvent event) {
        User user = event.getUser();
        // 收到事件,执行添加营销订阅
        marketingService.addUserToDefaultNewsletters(user);
    }
}
// 配置异步事件:让@Async生效(异步执行监听器,提高性能)
@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); // 判断该策略是否适用
}
// 策略1:新用户折扣(注册30天内的用户)
@Component
public class NewUserDiscountStrategy implements DiscountStrategy {
    @Value("${discount.new-user.percentage:10}")
    private int discountPercentage; // 折扣比例(从配置文件读取,默认10%)
    @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); // 注册时间在30天内
    }
}
// 策略2:会员折扣(VIP会员)
@Component
public class PremiumMemberDiscountStrategy implements DiscountStrategy {
    @Value("${discount.premium-member.percentage:15}")
    private int discountPercentage; // 会员折扣比例(默认15%)
    @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()); // 会员等级是PREMIUM
    }
}
// 策略3:大额订单折扣(订单金额超过阈值)
@Component
public class LargeOrderDiscountStrategy implements DiscountStrategy {
    @Value("${discount.large-order.threshold:1000}")
    private BigDecimal threshold; // 大额订单阈值(默认1000元)
    @Value("${discount.large-order.percentage:5}")
    private int discountPercentage; // 大额订单折扣比例(默认5%)
    @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;
    }
}

实战优势

算法独立: 每个算法都封装成单独的类,方便维护和修改

动态切换: 可以根据不同的场景,动态选择不同的算法(比如新用户自动用新用户折扣)

消除 if-else: 不用写一堆if (是新用户) { … } else if (是会员) { … }的代码

易扩展: 新增折扣策略(比如节日折扣),只需要加一个策略类,不用改旧代码

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

模式概述

“算法骨架师”:定义一个算法的骨架(步骤),把一些可变的步骤推迟到子类里实现 —— 相当于做蛋糕的食谱:步骤是固定的(准备材料→混合→烘烤→装饰),但装饰步骤可以自己发挥(抹奶油、放水果)。

SpringBoot 实战场景

SpringBoot 的JdbcTemplate、RestTemplate,全是它的经典实现!比如JdbcTemplate的查询流程(获取连接→创建 Statement→执行查询→处理结果→关闭连接)是固定的,处理结果的步骤(比如把 ResultSet 转换成对象)留给用户自己实现。

代码示例(报表导出场景)

// 抽象模板类:报表导出器(定义导出报表的固定步骤)
@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) {
            // 步骤7:处理异常(固定)
            handleExportError(e, request);
        }
    }
    // 固定方法:校验请求(子类不用管)
    protected void validateRequest(ReportRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("报表请求不能为null!");
        }
        if (request.getStartDate() == null || request.getEndDate() == null) {
            throw new IllegalArgumentException("开始日期和结束日期是必填项!");
        }
        if (request.getStartDate().isAfter(request.getEndDate())) {
            throw new IllegalArgumentException("开始日期不能晚于结束日期!");
        }
    }
    // 抽象方法:获取数据(子类必须实现,因为不同报表的数据来源不同)
    protected abstract ReportData fetchData(ReportRequest request);
    // 钩子方法:处理数据(子类可以选择重写,默认不处理)
    protected ReportData processData(ReportData data) {
        return data; // 默认不处理,直接返回原数据
    }
    // 抽象方法:格式化数据(子类必须实现,因为不同格式的报表(PDF/Excel)格式化方式不同)
    protected abstract byte[] formatData(ReportData data) throws IOException;
    // 固定方法:记录日志(子类不用管)
    protected void logExport(ReportRequest request, ReportData data) {
        System.out.println("报表导出成功!时间范围:" + 
                request.getStartDate() + " 到 " + request.getEndDate() + 
                ",记录数:" + data.getRecords().size());
    }
    // 固定方法:处理异常(子类不用管)
    protected void handleExportError(Exception e, ReportRequest request) {
        System.err.println("报表导出失败:" + e.getMessage());
        throw new ReportExportException("报表导出失败,请重试!", e);
    }
}
// 具体模板1:PDF报表导出器(实现抽象方法,处理PDF格式)
@Component("pdfExporter")
public class PdfReportExporter extends AbstractReportExporter {
    @Autowired
    private ReportRepository reportRepository;
    @Override
    protected ReportData fetchData(ReportRequest request) {
        // PDF报表的数据来源(从数据库查询)
        List<ReportRecord> records = reportRepository.findByDateRange(
                request.getStartDate(), request.getEndDate());
        return new ReportData(records, request.getStartDate(), request.getEndDate());
    }
    @Override
    protected ReportData processData(ReportData data) {
        // 重写钩子方法:对数据进行排序处理(PDF报表需要排序)
        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 {
        // 实现PDF格式化逻辑(用iText库)
        Document document = new Document();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            PdfWriter.getInstance(document, baos);
            document.open();
            // 添加报表标题
            document.add(new Paragraph("报表(" + data.getStartDate() + " 到 " + data.getEndDate() + ")"));
            // 创建PDF表格(3列:日期、描述、金额)
            PdfPTable table = new PdfPTable(3);
            table.addCell("日期");
            table.addCell("描述");
            table.addCell("金额");
            // 填充数据
            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();
    }
}
// 具体模板2:Excel报表导出器(实现抽象方法,处理Excel格式)
@Component("excelExporter")
public class ExcelReportExporter extends AbstractReportExporter {
    @Autowired
    private ReportRepository reportRepository;
    @Override
    protected ReportData fetchData(ReportRequest request) {
        // Excel报表的数据来源(和PDF一样,从数据库查询)
        List<ReportRecord> records = reportRepository.findByDateRange(
                request.getStartDate(), request.getEndDate());
        return new ReportData(records, request.getStartDate(), request.getEndDate());
    }
    // 不重写processData方法,使用父类的默认实现(Excel报表不需要额外处理数据)
    @Override
    protected byte[] formatData(ReportData data) throws IOException {
        // 实现Excel格式化逻辑(用POI库)
        Workbook workbook = new XSSFWorkbook();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            Sheet sheet = workbook.createSheet("报表数据");
            // 创建表头行
            Row headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("日期");
            headerRow.createCell(1).setCellValue("描述");
            headerRow.createCell(2).setCellValue("金额");
            // 填充数据行
            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;
    // 导出PDF报表
    @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());
    }
    // 导出Excel报表
    @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());
    }
}

实战优势

代码复用: 把固定的步骤(校验、日志、异常处理)提取到父类,子类只关注可变的步骤

控制扩展: 父类定义算法骨架,子类只能在指定的扩展点(抽象方法、钩子方法)修改,不会破坏算法结构

符合 “开闭原则”: 新增报表格式(比如 Word),只需要加一个子类,不用改父类的代码

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

模式概述

“请求接力赛”:把多个处理器组成一条链,请求从链的开头出发,依次经过每个处理器,直到有一个处理器能处理它 —— 相当于公司请假流程:员工→组长→部门经理→总经理,每个层级判断自己能不能批,不能批就交给下一级。

SpringBoot 实战场景

SpringBoot 的 Filter 链、Interceptor 链,全是它的实现!比如一个 HTTP 请求,会经过多个 Filter(登录校验 Filter、权限校验 Filter、日志 Filter),每个 Filter 处理完,再交给下一个 Filter,直到交给 DispatcherServlet。

代码示例(支付流程处理)

// 抽象处理器:支付处理器(定义处理请求的方法和下一个处理器)
public abstract class PaymentHandler {
    protected PaymentHandler nextHandler; // 下一个处理器(接力的人)
    // 设置下一个处理器(组装责任链)
    public void setNext(PaymentHandler handler) {
        this.nextHandler = handler;
    }
    // 处理支付请求(子类必须实现)
    public abstract PaymentResponse handle(PaymentRequest request);
}
// 处理器1:参数校验处理器(第一个接力的人,负责校验参数)
@Component
public class ValidationHandler extends PaymentHandler {
    @Override
    public PaymentResponse handle(PaymentRequest request) {
        // 校验支付金额
        if (request.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return new PaymentResponse(false, "支付金额必须大于0!");
        }
        // 校验卡号
        if (request.getCardNumber() == null || request.getCardNumber().isEmpty()) {
            return new PaymentResponse(false, "银行卡号不能为空!");
        }
        // 校验卡号长度(13-19位)
        if (request.getCardNumber().length() < 13 || request.getCardNumber().length() > 19) {
            return new PaymentResponse(false, "银行卡号长度无效!");
        }
        // 校验有效期
        if (request.getExpiryDate() == null) {
            return new PaymentResponse(false, "银行卡有效期不能为空!");
        }
        if (request.getExpiryDate().isBefore(YearMonth.now())) {
            return new PaymentResponse(false, "银行卡已过期!");
        }
        // 校验通过,交给下一个处理器
        if (nextHandler != null) {
            return nextHandler.handle(request);
        }
        return new PaymentResponse(true, "参数校验通过!");
    }
}
// 处理器2:风控处理器(第二个接力的人,负责检测欺诈)
@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, "交易存在欺诈风险:" + checkResult.getReason());
        }
        // 风控通过,交给下一个处理器
        if (nextHandler != null) {
            return nextHandler.handle(request);
        }
        return new PaymentResponse(true, "风控检测通过!");
    }
}
// 处理器3:支付处理处理器(第三个接力的人,负责实际支付)
@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, "支付失败:" + 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, "支付处理成功!", gatewayResponse.getTransactionId());
    }
}
// 处理器4:通知处理器(第四个接力的人,负责支付结果通知)
@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, "支付完成且通知已发送!");
    }
}
// 责任链配置:组装处理器链条
@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(); // 获取命令描述(日志用)
}
// 具体命令1:创建订单命令
@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 "创建订单(客户ID:" + orderToCreate.getCustomerId() + ")";
    }
}
// 具体命令2:扣减库存命令
@Component
public class DeductInventoryCommand implements Command {
    private final InventoryService inventoryService;
    private final Long productId; // 商品ID
    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 "扣减库存(商品ID:" + productId + ",数量:" + quantity + ")";
    }
}
// 具体命令3:处理支付命令
@Component
public class ProcessPaymentCommand implements Command {
    private final PaymentService paymentService;
    private final PaymentRequest paymentRequest; // 支付请求数据
    private String transactionId; // 保存支付交易ID,用于撤销(退款)
    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());
        }
        transactionId = response.getTransactionId();
    }
    @Override
    public void undo() {
        // 撤销“处理支付”:发起退款
        if (transactionId != null) {
            paymentService.refundPayment(transactionId);
            transactionId = null;
        }
    }
    @Override
    public String getDescription() {
        return "处理支付(订单ID:" + paymentRequest.getOrderId() + ",金额:" + paymentRequest.getAmount() + ")";
    }
}
// 命令历史:记录已执行的命令(用于撤销)
@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);
                }
                // 所有命令执行成功,批量记录到历史
                executedCommands.forEach(history::push);
                return null;
            } catch (Exception e) {
                // 执行失败,反向撤销已执行的命令(比如先撤销“支付”,再撤销“扣库存”,最后撤销“创建订单”)
                Collections.reverse(executedCommands);
                executedCommands.forEach(Command::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) {
        // 1. 组装订单数据
        Order order = new Order();
        order.setCustomerId(orderRequest.getCustomerId());
        order.setItems(orderRequest.getItems());
        order.setTotalAmount(calculateTotal(orderRequest.getItems()));
        // 2. 组装支付请求数据
        PaymentRequest paymentRequest = new PaymentRequest();
        paymentRequest.setAmount(order.getTotalAmount());
        paymentRequest.setCardNumber(orderRequest.getPaymentDetails().getCardNumber());
        paymentRequest.setExpiryDate(orderRequest.getPaymentDetails().getExpiryDate());
        paymentRequest.setCvv(orderRequest.getPaymentDetails().getCvv());
        paymentRequest.setOrderId(order.getId()); // 关联订单ID
        // 3. 组装命令列表(按执行顺序)
        List<Command> commands = new ArrayList<>();
        // 命令1:创建订单
        commands.add(new CreateOrderCommand(orderService, orderService.getRepository(), order));
        // 命令2:给每个商品扣减库存
        for (OrderItem item : order.getItems()) {
            commands.add(new DeductInventoryCommand(inventoryService, item.getProductId(), item.getQuantity()));
        }
        // 命令3:处理支付
        commands.add(new ProcessPaymentCommand(paymentService, paymentRequest));
        // 4. 调用命令执行器,批量执行命令
        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);
    }
}

实战优势

解耦请求与执行: 下单服务只需要组装命令,不用关心每个步骤怎么执行;执行逻辑封装在命令里,修改时互不影响。

支持撤销 / 重做: 每个命令都有undo方法,出错时能按顺序撤销,保证数据一致性(比如支付失败,自动回滚库存和订单)。

组合复杂操作: 把多个简单命令组合成复杂流程(如下单 = 创建订单 + 扣库存 + 支付),代码清晰且易扩展。

方便日志与监控: 通过CommandHistory能记录所有执行过的命令,便于排查问题和做审计日志。

13. 状态模式(State Pattern)

模式概述

“对象状态管家”:让对象的行为随着内部状态的变化而变化 —— 比如订单有 “新建”“已确认”“已支付”“已发货” 等状态,每个状态下能执行的操作不同(“新建” 状态能确认,不能发货;“已支付” 状态能发货,不能取消),把每个状态的行为封装成独立类,避免一堆if-else判断。

SpringBoot 实战场景

订单状态管理、支付状态流转、工作流审批(比如请假单 “待审批”“已批准”“已驳回”)都常用它!SpringBoot 中结合@Component能把每个状态托管给容器,实现状态的灵活切换。

代码示例(订单状态流转)

// 订单状态接口:定义各状态支持的行为
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();              // 获取状态标识(如“NEW”“PAID”)
}
// 具体状态1:新建状态(NEW)
@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("未确认的订单无法支付!");
    }
    @Override
    public OrderState ship(Order order) {
        throw new IllegalStateException("未确认未支付的订单无法发货!");
    }
    @Override
    public OrderState deliver(Order order) {
        throw new IllegalStateException("未发货的订单无法确认收货!");
    }
    @Override
    public OrderState cancel(Order order) {
        // 执行“取消订单”逻辑:记录取消时间和原因
        order.setCancelledAt(LocalDateTime.now());
        order.setCancellationReason("客户在确认前取消订单");
        return cancelledOrderState; // 切换到“已取消”状态
    }
    @Override
    public OrderState refund(Order order) {
        throw new IllegalStateException("未支付的订单无法退款!");
    }
    @Override
    public String getStatus() {
        return "NEW";
    }
}
// 具体状态2:已确认状态(CONFIRMED)
@Component
public class ConfirmedOrderState implements OrderState {
    @Autowired
    private PaidOrderState paidOrderState; // 下一个状态:已支付
    @Autowired
    private CancelledOrderState cancelledOrderState; // 下一个状态:已取消
    @Override
    public OrderState confirm(Order order) {
        throw new IllegalStateException("订单已确认,无需重复确认!");
    }
    @Override
    public OrderState pay(Order order) {
        // 执行“支付订单”逻辑:记录支付时间
        order.setPaidAt(LocalDateTime.now());
        return paidOrderState; // 切换到“已支付”状态
    }
    @Override
    public OrderState ship(Order order) {
        throw new IllegalStateException("未支付的订单无法发货!");
    }
    @Override
    public OrderState deliver(Order order) {
        throw new IllegalStateException("未发货的订单无法确认收货!");
    }
    @Override
    public OrderState cancel(Order order) {
        order.setCancelledAt(LocalDateTime.now());
        order.setCancellationReason("客户在支付前取消订单");
        return cancelledOrderState;
    }
    @Override
    public OrderState refund(Order order) {
        throw new IllegalStateException("未支付的订单无法退款!");
    }
       @Override
    public String getStatus() {
        return "CONFIRMED";
    }
}
// 具体状态3:已支付状态(PAID)
@Component
public class PaidOrderState implements OrderState {
    @Autowired
    private ShippedOrderState shippedOrderState; // 下一个状态:已发货
    @Autowired
    private RefundedOrderState refundedOrderState; // 下一个状态:已退款
    @Override
    public OrderState confirm(Order order) {
        throw new IllegalStateException("订单已支付,无需重复确认!");
    }
    @Override
    public OrderState pay(Order order) {
        throw new IllegalStateException("订单已支付,无需重复支付!");
    }
    @Override
    public OrderState ship(Order order) {
        // 执行“发货”逻辑:记录发货时间
        order.setShippedAt(LocalDateTime.now());
        return shippedOrderState; // 切换到“已发货”状态
    }
    @Override
    public OrderState deliver(Order order) {
        throw new IllegalStateException("未发货的订单无法确认收货!");
    }
    @Override
    public OrderState cancel(Order order) {
        throw new IllegalStateException("已支付的订单无法取消,请申请退款!");
    }
    @Override
    public OrderState refund(Order order) {
        // 执行“退款”逻辑:记录退款时间
        order.setRefundedAt(LocalDateTime.now());
        return refundedOrderState; // 切换到“已退款”状态
    }
    @Override
    public String getStatus() {
        return "PAID";
    }
}
// 具体状态4:已发货状态(SHIPPED)
@Component
public class ShippedOrderState implements OrderState {
    @Autowired
    private DeliveredOrderState deliveredOrderState; // 下一个状态:已收货
    @Override
    public OrderState confirm(Order order) {
        throw new IllegalStateException("订单已发货,无需重复确认!");
    }
    @Override
    public OrderState pay(Order order) {
        throw new IllegalStateException("订单已支付,无需重复支付!");
    }
    @Override
    public OrderState ship(Order order) {
        throw new IllegalStateException("订单已发货,无需重复发货!");
    }
    @Override
    public OrderState deliver(Order order) {
        // 执行“确认收货”逻辑:记录收货时间
        order.setDeliveredAt(LocalDateTime.now());
        return deliveredOrderState; // 切换到“已收货”状态
    }
    @Override
    public OrderState cancel(Order order) {
        throw new IllegalStateException("已发货的订单无法取消,可申请退货退款!");
    }
    @Override
    public OrderState refund(Order order) {
        throw new IllegalStateException("已发货未收货的订单,需先确认收货/退货后再退款!");
    }
    @Override
    public String getStatus() {
        return "SHIPPED";
    }
}
// 具体状态5:已收货状态(DELIVERED)
@Component
public class DeliveredOrderState implements OrderState {
    @Autowired
    private RefundedOrderState refundedOrderState; // 下一个状态:已退款
    @Override
    public OrderState confirm(Order order) {
        throw new IllegalStateException("订单已完成收货,无需确认!");
    }
    @Override
    public OrderState pay(Order order) {
        throw new IllegalStateException("订单已支付,无需重复支付!");
    }
    @Override
    public OrderState ship(Order order) {
        throw new IllegalStateException("订单已收货,无需发货!");
    }
    @Override
    public OrderState deliver(Order order) {
        throw new IllegalStateException("订单已完成收货,无需重复确认!");
    }
    @Override
    public OrderState cancel(Order order) {
        throw new IllegalStateException("已收货的订单无法取消,可申请售后退款!");
    }
    @Override
    public OrderState refund(Order order) {
        // 执行“售后退款”逻辑:记录退款时间
        order.setRefundedAt(LocalDateTime.now());
        return refundedOrderState; // 切换到“已退款”状态
    }
    @Override
    public String getStatus() {
        return "DELIVERED";
    }
}
// 具体状态6:已取消状态(CANCELLED)
@Component
public class CancelledOrderState implements OrderState {
    @Override
    public OrderState confirm(Order order) {
        throw new IllegalStateException("已取消的订单无法确认!");
    }
    @Override
    public OrderState pay(Order order) {
        throw new IllegalStateException("已取消的订单无法支付!");
    }
    @Override
    public OrderState ship(Order order) {
        throw new IllegalStateException("已取消的订单无法发货!");
    }
    @Override
    public OrderState deliver(Order order) {
        throw new IllegalStateException("已取消的订单无法确认收货!");
    }
    @Override
    public OrderState cancel(Order order) {
        throw new IllegalStateException("订单已取消,无需重复取消!");
    }
    @Override
    public OrderState refund(Order order) {
        throw new IllegalStateException("未支付的取消订单无需退款!");
    }
    @Override
    public String getStatus() {
        return "CANCELLED";
    }
}
// 具体状态7:已退款状态(REFUNDED)
@Component
public class RefundedOrderState implements OrderState {
    @Override
    public OrderState confirm(Order order) {
        throw new IllegalStateException("已退款的订单无法确认!");
    }
    @Override
    public OrderState pay(Order order) {
        throw new IllegalStateException("已退款的订单无需支付!");
    }
    @Override
    public OrderState ship(Order order) {
        throw new IllegalStateException("已退款的订单无法发货!");
    }
    @Override
    public OrderState deliver(Order order) {
        throw new IllegalStateException("已退款的订单无法确认收货!");
    }
    @Override
    public OrderState cancel(Order order) {
        throw new IllegalStateException("已退款的订单无需取消!");
    }
    @Override
    public OrderState refund(Order order) {
        throw new IllegalStateException("订单已退款,无需重复退款!");
    }
    @Override
    public String getStatus() {
        return "REFUNDED";
    }
}
// 订单实体:状态上下文(持有当前状态,触发状态切换)
@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"; // 持久化状态标识
    // 加载实体时初始化状态(从数据库status字段恢复currentState)
    @PostLoad
    private void onLoad() {
        initState();
    }
    private void initState() {
        if (status == null) status = "NEW";
        // 根据状态标识,从Spring容器获取对应的状态实例
        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("未知订单状态:" + 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();
    }
}
// Spring上下文工具:给实体类注入Spring Bean(关键)
@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
    // 静态方法获取Bean(实体类无法直接@Autowired,用这个工具类)
    public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
    }
}
// 订单服务:业务层调用状态切换
@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(); // 触发状态切换:NEW → CONFIRMED
        return orderRepository.save(order);
    }
    @Transactional
    public Order payOrder(Long orderId) {
        Order order = findOrderById(orderId);
        order.pay(); // 触发状态切换:CONFIRMED → PAID
        return orderRepository.save(order);
    }
    @Transactional
    public Order shipOrder(Long orderId) {
        Order order = findOrderById(orderId);
        order.ship(); // 触发状态切换:PAID → SHIPPED
        return orderRepository.save(order);
    }
    @Transactional
    public Order deliverOrder(Long orderId) {
        Order order = findOrderById(orderId);
        order.deliver(); // 触发状态切换:SHIPPED → DELIVERED
        return orderRepository.save(order);
    }
    @Transactional
    public Order cancelOrder(Long orderId) {
        Order order = findOrderById(orderId);
        order.cancel(); // 触发状态切换(比如NEW → CANCELLED)
        return orderRepository.save(order);
    }
    @Transactional
    public Order refundOrder(Long orderId) {
        Order order = findOrderById(orderId);
        order.refund(); // 触发状态切换(比如PAID → REFUNDED)
        return orderRepository.save(order);
    }
    private Order findOrderById(Long orderId) {
        return orderRepository.findById(orderId)
                .orElseThrow(() -> new OrderNotFoundException("订单不存在:" + orderId));
    }
    // 给外部暴露Repository(命令模式里要用)
    public OrderRepository getRepository() {
        return orderRepository;
    }
}
// 自定义异常:订单不存在
public class OrderNotFoundException extends RuntimeException {
    public OrderNotFoundException(String message) {
        super(message);
    }
}
// 自定义异常:支付失败
public class PaymentFailedException extends RuntimeException {
    public PaymentFailedException(String message) {
        super(message);
    }
}
// 自定义异常:报表导出失败
public class ReportExportException extends RuntimeException {
    public ReportExportException(String message, Throwable cause) {
        super(message, cause);
    }
}

实战优势

状态行为封装: 每个状态的行为都在独立类里,比如 “新建状态能做什么” 全在NewOrderState里,代码清晰,不用翻一堆if-else。

状态切换清晰: 状态之间的流转规则(比如 NEW→CONFIRMED,CONFIRMED→PAID)由状态类自己控制,逻辑不混乱。

易扩展新状态: 新增 “已拒收” 状态,只需写RejectedOrderState类,实现OrderState接口,修改状态流转规则即可,不用改原有状态代码。

避免状态混乱: 每个状态只暴露自己支持的行为,比如 “已支付” 状态不能调用cancel(),从代码层面防止非法操作。

设计模式不是 “银弹”,是 “工具箱”

实际开发中,这些模式很少单独用 —— 比如订单下单流程,会同时用到命令模式(封装每个步骤)、状态模式(管理订单状态)、观察者模式(下单成功后发通知)。

掌握设计模式的核心不是 “死记硬背每种模式的代码”,而是理解它要解决的问题:比如解耦、复用、扩展。遇到复杂业务时,从 “工具箱” 里挑合适的 “工具” 组合使用,而不是为了用模式而用模式(避免过度设计)。

最后记住:代码是给人看的,其次才是给机器执行的。设计模式的最终目的,是让代码更易懂、更易维护 —— 这才是 “优雅代码” 的本质~

要是你还想整点进阶玩法,比如把这些模式整合到一个完整的电商项目里,或者整理成面试高频题 + 答题思路,只管说!咱主打一个有求必应~

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。