java中23种设计模式

单例模式(Singleton Pattern)

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

SpringBoot 实战场景

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

代码示例

bash 复制代码
@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 对象,减少 "内存垃圾"

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

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

工厂方法模式(Factory Method Pattern)

模式概述

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

SpringBoot 实战场景

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

代码示例

bash 复制代码
// 支付处理器接口:相当于"生产规范"
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)不用知道具体是哪种支付,只管 "付钱"

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

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

抽象工厂模式(Abstract Factory Pattern)

模式概述

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

SpringBoot 实战场景

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

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

bash 复制代码
// 抽象产品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),只需要加一个具体工厂和对应的产品实现

建造者模式(Builder Pattern)

模式概述

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

SpringBoot 实战场景

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

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

bash 复制代码
// 产品类:邮件对象
@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,能组装出不同参数的对象(比如有的邮件有附件,有的没有)

原型模式(Prototype Pattern)

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

SpringBoot 实战场景

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

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

bash 复制代码
// 报表配置类(支持克隆,相当于"原型")
@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;
    }
}

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

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

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

适配器模式(Adapter Pattern)

模式概述

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

SpringBoot 实战场景

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

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

bash 复制代码
// 老支付系统接口( 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 {
            // 支付失败逻辑
        }
    }
}

实战优势
复用老代码:不用重写祖传代码,加个适配器就能在新系统里用

平滑过渡:新旧系统并行运行,慢慢迁移,不影响业务

解耦:新系统不用关心老接口的细节,只管调用新接口

装饰器模式(Decorator Pattern)

模式概述
"对象的穿衣大师":动态给对象加 "新技能",不用改原对象的代码 ------ 相当于给手机贴钢化膜(加保护)、装手机壳(加颜值),手机本身没变,但多了新功能。

SpringBoot 实战场景

SpringBoot 的@Cacheable、@Transactional注解,全是它的杰作!比如一个普通的查询方法,加个@Cacheable,就多了 "缓存" 功能;加个@Transactional,就多了 "事务" 功能 ------ 原方法代码一点没改。

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

bash 复制代码
// 基础接口:通知服务(核心功能:发通知)
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( Math.pow(2, attempts) * 100L);
                } 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());
    }
}

实战优势

动态增强:不用改原代码,就能给对象加新功能(符合 "开闭原则")

组合灵活:多个装饰器可以自由组合(比如有的场景需要 "日志 + 重试",有的需要 "加密 + 日志")

接口一致:装饰后的对象和原对象接口一样,调用方不用改代码

观察者模式(Observer Pattern)

模式概述

"消息广播员":定义一对多的关系,当一个对象(广播员)状态变化时,所有依赖它的对象(听众)都会收到通知,自动更新 ------ 相当于公众号发推文,所有关注的人都会收到消息。

SpringBoot 实战场景

SpringBoot 的事件机制(ApplicationEvent、ApplicationListener)就是它的实现!比如用户注册成功后,要发欢迎邮件、创建用户档案、添加营销订阅,这些操作都可以作为 "听众",监听 "用户注册" 这个事件。

代码示例(用户注册事件)

bash 复制代码
// 自定义事件:用户注册事件(相当于"推文")
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;
    }
}

实战优势
解耦:发布者不用知道有哪些听众,只管发布事件;听众不用知道发布者的细节,只管监听事件

异步处理:支持异步执行监听器,不会阻塞主线程(比如添加营销订阅比较耗时,异步执行不影响用户注册的响应速度)

易扩展:新增一个操作(比如注册后送积分),只需要加一个监听器,不用改发布者的代码

策略模式(Strategy Pattern)

模式概述
"算法切换大师":定义一组算法,把每个算法都封装起来,让它们可以互相替换 ------ 相当于手机的 "拍照模式",普通模式、夜景模式、人像模式,按需切换,核心都是 "拍照"。

SpringBoot 实战场景

SpringBoot 的缓存策略、认证策略,全是它的应用!比如电商的折扣策略:新用户折扣、会员折扣、大额订单折扣,不同用户 / 订单用不同的折扣算法,随时可以切换。

代码示例(折扣策略)

bash 复制代码
// 折扣策略接口:定义"折扣算法"的规范
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 (是会员) { ... }的代码

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

模板方法模式(Template Method Pattern)

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

SpringBoot 实战场景

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

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

bash 复制代码
// 抽象模板类:报表导出器(定义导出报表的固定步骤)
@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),只需要加一个子类,不用改父类的代码

责任链模式(Chain of Responsibility Pattern)

模式概述

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

SpringBoot 实战场景

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

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

bash 复制代码
// 抽象处理器:支付处理器(定义处理请求的方法和下一个处理器)
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);
    }
}

实战优势
解耦请求方与处理方:支付服务只需要调用责任链入口,不用知道具体有哪些处理器、每个处理器做什么。

灵活调整流程:新增 / 移除处理器(比如加 "优惠券抵扣处理器"),只需改配置,不用改业务代码;调整处理器顺序也很方便。

单一职责:每个处理器只做一件事(校验 / 风控 / 支付 / 通知),代码清晰、易维护。

扩展性强:后续要加新的处理步骤,直接写新的处理器类,接入链条即可,完全符合 "开闭原则"。

命令模式(Command Pattern)

模式概述

"请求封装大师":把一个请求(比如 "创建订单""扣减库存")封装成一个对象,将 "发请求的人" 和 "处理请求的人" 解耦 ------ 相当于餐厅里的菜单:顾客(请求方)只需要点菜单(命令对象),厨师(处理方)按菜单做菜,双方不用直接沟通。

SpringBoot 实战场景

SpringBoot 的事件处理、任务调度、事务回滚都常用它!比如订单下单流程:创建订单、扣减库存、处理支付,每个步骤封装成一个命令,既能按顺序执行,也能在出错时反向撤销(比如支付失败,就撤销 "扣减库存" 和 "创建订单")。

代码示例(订单下单流程)

bash 复制代码
// 命令接口:定义执行和撤销行为
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能记录所有执行过的命令,便于排查问题和做审计日志。

状态模式(State Pattern)

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

SpringBoot 实战场景

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

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

bash 复制代码
// 订单状态接口:定义各状态支持的行为
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(),从代码层面防止非法操作。


以下是一些在开发过程中使用频率不是这么高的设计模式

桥接模式(Bridge Pattern)

核心思想 :将抽象部分与实现部分分离,使它们可以独立地变化。
实现方式 :通过定义抽象类和实现类,将它们的变化解耦。
应用场景:不同图形API(OpenGL/Vulkan)与形状(圆/方)的组合。

优点
解耦 :抽象和实现的解耦,使得它们可以独立变化。
灵活性 :可以独立地扩展抽象和实现。
Java 示例:

bash 复制代码
// 实现接口
public interface Implementor {
    void operation();
}

// 具体实现A
public class ConcreteImplementorA implements Implementor {
    @Override
    public void operation() {
        System.out.println("ConcreteImplementorA operation");
    }
}

// 具体实现B
public class ConcreteImplementorB implements Implementor {
    @Override
    public void operation() {
        System.out.println("ConcreteImplementorB operation");
    }
}

// 抽象类
public abstract class Abstraction {
    protected Implementor implementor;

    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    public abstract void operation();
}

// 扩展抽象类
public class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operation() {
        implementor.operation();  // 委托给实现类
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Implementor implementorA = new ConcreteImplementorA();
        Abstraction abstraction = new RefinedAbstraction(implementorA);
        abstraction.operation();

        Implementor implementorB = new ConcreteImplementorB();
        abstraction = new RefinedAbstraction(implementorB);
        abstraction.operation();
    }
}

组合模式(Composite Pattern)

核心思想: 将对象组合成树形结构以表示部分-整体层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
实现方式 :通过定义一个组件接口,将叶子节点和容器节点统一处理。
应用场景:文件系统(文件/文件夹统一处理)、UI 容器组件)。

优点:

一致性 :对单个对象和组合对象的一致性操作。
简化客户端代码 :客户端代码可以统一处理叶子节点和容器节点。
Java 示例

bash 复制代码
import java.util.ArrayList;
import java.util.List;

// 组件接口
public interface Component {
    void operation();
}

// 叶子节点
public class Leaf implements Component {
    @Override
    public void operation() {
        System.out.println("Leaf operation");
    }
}

// 容器节点
public class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public void operation() {
        for (Component child : children) {
            child.operation();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Composite root = new Composite();
        Component leaf1 = new Leaf();
        Component leaf2 = new Leaf();

        root.add(leaf1);
        root.add(leaf2);

        root.operation();  // 统一调用
    }
}

外观模式(Facade Pattern)

核心思想 :为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。
实现方式 :通过定义一个外观类来封装子系统的复杂性,提供简化的接口。
应用场景:Spring 的 JdbcUtils 封装数据库操作细节。

优点:

简化使用 :提供简单的接口来访问复杂的子系统。
解耦 :将客户端与子系统解耦。
Java 示例:

bash 复制代码
// 子系统类A
public class SubsystemA {
    public void operationA() {
        System.out.println("SubsystemA operationA");
    }
}

// 子系统类B
public class SubsystemB {
    public void operationB() {
        System.out.println("SubsystemB operationB");
    }
}

// 外观类
public class Facade {
    private SubsystemA subsystemA;
    private SubsystemB subsystemB;

    public Facade() {
        subsystemA = new SubsystemA();
        subsystemB = new SubsystemB();
    }

    public void operation() {
        subsystemA.operationA();
        subsystemB.operationB();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.operation();  // 通过外观类调用子系统
    }
}

享元模式(Flyweight Pattern)

核心思想 :运用共享技术有效地支持大量细粒度的对象。
实现方式 :通过将对象的共享部分与独享部分分开,将共享部分提取出来。
应用场景:棋类游戏的棋子对象复用、字符串常量池。

优点:

节省内存 :通过共享来减少内存使用。
提高性能 :减少对象创建和管理的开销。
Java 示例:

bash 复制代码
import java.util.HashMap;
import java.util.Map;

// 享元接口
public interface Flyweight {
    void operation(String extrinsicState);
}

// 具体享元类
public class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;

    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void operation(String extrinsicState) {
        System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
    }
}

// 享元工厂
public class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String key) {
        Flyweight flyweight = flyweights.get(key);
        if (flyweight == null) {
            flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
        }
        return flyweight;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight1 = factory.getFlyweight("A");
        Flyweight flyweight2 = factory.getFlyweight("B");
        flyweight1.operation("1");
        flyweight2.operation("2");
    }
}

代理模式(Proxy Pattern)

核心思想 :为其他对象提供一种代理以控制对这个对象的访问。
实现方式 :通过定义代理类来控制对真实对象的访问。
应用场景:AOP 实现、RPC 调用。

优点:

控制访问 :可以在代理中实现对真实对象的控制。
增强功能 :可以在代理中增加额外的功能,如延迟加载。
Java 示例:

bash 复制代码
// 抽象主题接口
public interface Subject {
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject request");
    }
}

// 代理类
public class Proxy implements Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();  // 代理控制对真实主题的访问
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Subject proxy = new Proxy();
        proxy.request();  // 通过代理访问真实主题
    }
}

迭代器模式(Iterator Pattern)

核心思想 :提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部表示。
实现方式 :通过定义迭代器接口和具体迭代器类来遍历集合对象中的元素。
应用场景:集合类、数据库查询结果等。

优点:

简化访问 :提供统一的访问方式。
解耦 :容器和迭代器解耦。
Java 示例

bash 复制代码
import java.util.ArrayList;
import java.util.List;

// 迭代器接口
public interface Iterator {
    boolean hasNext();
    Object next();
}

// 具体迭代器类
public class ConcreteIterator implements Iterator {
    private List<Object> items;
    private int position;

    public ConcreteIterator(List<Object> items) {
        this.items = items;
    }

    @Override
    public boolean hasNext() {
        return position < items.size();
    }

    @Override
    public Object next() {
        return items.get(position++);
    }
}

// 聚合类
public class Aggregate {
    private List<Object> items = new ArrayList<>();

    public void add(Object item) {
        items.add(item);
    }

    public Iterator iterator() {
        return new ConcreteIterator(items);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Aggregate aggregate = new Aggregate();
        aggregate.add("Item 1");
        aggregate.add("Item 2");

        Iterator iterator = aggregate.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

中介者模式(Mediator Pattern)

核心思想: 定义一个对象来封装一组对象之间的交互,使得对象之间的耦合松散,从而使得它们可以独立地改变。
实现方式 :通过定义中介者接口和具体中介者类来协调对象之间的交互。
应用场景:聊天室消息转发、MVC 控制器。

优点:

降低耦合 :将对象间的交互集中在中介者中。
易于维护 :中介者可以集中处理复杂的交互逻辑。
Java 示例:

bash 复制代码
// 中介者接口
public interface Mediator {
    void notify(Component sender, String event);
}


// 组件接口
public abstract class Component {
    protected Mediator mediator;

    public Component(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void handleEvent(String event);
}

// 具体组件A
public class ComponentA extends Component {
    public ComponentA(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void handleEvent(String event) {
        System.out.println("ComponentA handling event: "

 + event);
    }

    public void triggerEvent(String event) {
        mediator.notify(this, event);
    }
}

// 具体组件B
public class ComponentB extends Component {
    public ComponentB(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void handleEvent(String event) {
        System.out.println("ComponentB handling event: " + event);
    }
}
// 具体中介者类
public class ConcreteMediator implements Mediator {
    private ComponentA componentA;
    private ComponentB componentB;

    public void setComponentA(ComponentA componentA) {
        this.componentA = componentA;
    }

    public void setComponentB(ComponentB componentB) {
        this.componentB = componentB;
    }

    @Override
    public void notify(Component sender, String event) {
        if (sender == componentA) {
            componentB.handleEvent(event);
        } else if (sender == componentB) {
            componentA.handleEvent(event);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();
        ComponentA componentA = new ComponentA(mediator);
        ComponentB componentB = new ComponentB(mediator);
        mediator.setComponentA(componentA);
        mediator.setComponentB(componentB);

        componentA.triggerEvent("Event A");
        componentB.handleEvent("Event B");
    }
}

备忘录模式(Memento Pattern)

核心思想 :在不暴露对象内部状态的情况下,捕获一个对象的内部状态,并在该对象外部保存这个状态。可以在以后将对象恢复到保存的状态。
实现方式 :通过定义备忘录类来保存对象的状态,并通过发起人类和恢复者类来实现状态的恢复。
应用场景:文本编辑器撤销功能、游戏存档。

优点:

状态恢复 :可以在需要的时候恢复对象的状态。
封装性 :不暴露对象的内部状态。
Java 示例:

bash 复制代码
// 备忘录类
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

// 发起人类
public class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}

// 管理者类
public class Caretaker {
    private Memento memento;

    public void saveMemento(Memento memento) {
        this.memento = memento;
    }

    public Memento retrieveMemento() {
        return memento;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        originator.setState("State1");
        caretaker.saveMemento(originator.saveStateToMemento());

        originator.setState("State2");
        System.out.println("Current State: " + originator.getState());

        originator.getStateFromMemento(caretaker.retrieveMemento());
        System.out.println("Restored State: " + originator.getState());
    }
}

解释器模式(Interpreter Pattern)

核心思想 :给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
实现方式 :通过定义解释器类和表达式类,将文法规则和解释逻辑分开。
应用场景:编译器、SQL 解析器、游戏规则引擎。

优点:

易于扩展 :可以通过增加新的终结符和非终结符来扩展语法。
灵活性 :可以定义复杂的语言规则。
Java 示例:

bash 复制代码
import java.util.HashMap;
import java.util.Map;

// 表达式接口
public interface Expression {
    int interpret(Map<String, Integer> context);
}

// 终结符表达式
public class NumberExpression implements Expression {
    private int number;

    public NumberExpression(int number) {
        this.number = number;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return number;
    }
}

// 非终结符表达式
public class PlusExpression implements Expression {
    private Expression left;
    private Expression right;

    public PlusExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Expression expression = new PlusExpression(new NumberExpression(5), new NumberExpression(3));
        Map<String, Integer> context = new HashMap<>();
        int result = expression.interpret(context);
        System.out.println("Result: " + result);  // 输出结果 8
    }
}

访问者模式(Visitor Pattern)

核心思想 :表示一个作用于某对象结构中的各元素的操作,它可以在不改变元素类的前提下定义作用于这些元素的新操作。
实现方式 :通过定义访问者接口和具体访问者类,将操作和对象结构分离,使得可以在不改变对象结构的情况下增加新的操作。
应用场景:编译器语法树分析、复杂对象结构遍历。

优点:

扩展性 :可以在不改变对象结构的情况下增加新的操作。
操作集中 :操作被集中在访问者中,使得相关操作更易于维护。
Java 示例

bash 复制代码
import java.util.ArrayList;
import java.util.List;

// 访问者接口
public interface Visitor {
    void visit(ConcreteElementA elementA);
    void visit(ConcreteElementB elementB);
}

// 具体访问者A
public class ConcreteVisitorA implements Visitor {
    @Override
    public void visit(ConcreteElementA elementA) {
        System.out.println("Visitor A visiting Element A");
    }

    @Override
    public void visit(ConcreteElementB elementB) {
        System.out.println("Visitor A visiting Element B");
    }
}

// 具体访问者B
public class ConcreteVisitorB implements Visitor {
    @Override
    public void visit(ConcreteElementA elementA) {
        System.out.println("Visitor B visiting Element A");
    }

    @Override
    public void visit(ConcreteElementB elementB) {
        System.out.println("Visitor B visiting Element B");
    }
}

// 元素接口
public interface Element {
    void accept(Visitor visitor);
}

// 具体元素A
public class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素B
public class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 对象结构
public class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void addElement(Element element) {
        elements.add(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ObjectStructure structure = new ObjectStructure();
        structure.addElement(new ConcreteElementA());
        structure.addElement(new ConcreteElementB());

        Visitor visitorA = new ConcreteVisitorA();
        structure.accept(visitorA);  // Visitor A visiting elements

        Visitor visitorB = new ConcreteVisitorB();
        structure.accept(visitorB);  // Visitor B visiting elements
    }
}
相关推荐
Scott9999HH2 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔2 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社3 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海3 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖4 小时前
JDK 26 新特性详解
java·开发语言
马优晨5 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大7 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai7 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说7 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json