设计模式是前辈们总结的代码设计经验,是解决特定场景问题的 “最优解模板”。在 Java 开发中,无论是 JDK 源码、SpringBoot 框架,还是企业级业务系统,设计模式都无处不在。掌握设计模式,不仅能提升代码的可读性、可扩展性,更是从 “初级开发者” 迈向 “中级开发者” 的关键一步。

今天,我将聚焦 Java 中最常用的 8 种设计模式,结合 JDK 源码、SpringBoot 底层实现和企业级实战场景,用 “原理 + 场景 + 代码” 的方式深度拆解,让你看完就能用在项目中。

一、设计模式总览:为什么要学设计模式?

1. 设计模式的核心价值

  • 解耦:分离业务逻辑与通用逻辑,降低代码耦合度;
  • 复用:通用模板直接复用,减少重复编码;
  • 扩展:符合开闭原则(对扩展开放,对修改关闭),应对需求变更更灵活;
  • 规范:统一代码设计风格,提升团队协作效率。

2. 常用设计模式分类(聚焦高频)

类型 常用模式 核心作用
创建型 单例模式、工厂模式、建造者模式 控制对象创建过程,降低创建成本
结构型 代理模式、装饰器模式、适配器模式 优化类 / 对象的组合关系,提升灵活性
行为型 策略模式、观察者模式 优化对象间的交互逻辑,解耦行为依赖

这些模式是企业开发中 “出场率” 最高的,尤其是 SpringBoot 框架几乎无缝集成了所有模式,我们逐一拆解。

二、创建型模式:如何优雅地创建对象?

创建型模式的核心是 “控制对象创建”,避免硬编码 new 对象导致的耦合问题。

1. 单例模式:全局唯一实例

(1)核心原理

保证一个类在整个应用中只有一个实例,且提供全局访问点。

(2)应用场景
  • 无状态工具类(如日志工具类、配置工具类);
  • 资源密集型对象(如数据库连接池、线程池);
  • SpringBoot 中的 Bean 默认是单例模式(scope="singleton")。
(3)实战代码(推荐:双重检查锁 DCL 模式,JDK1.8 + 安全)
/**
 * 单例模式:双重检查锁(DCL),线程安全且高效
 */
public class Singleton {
    // volatile关键字:禁止指令重排序,保证instance可见性
    private static volatile Singleton instance;

    // 私有构造器:禁止外部new对象
    private Singleton() {}

    // 全局访问点
    public static Singleton getInstance() {
        // 第一次检查:避免频繁加锁(性能优化)
        if (instance == null) {
            // 加锁:保证多线程安全
            synchronized (Singleton.class) {
                // 第二次检查:防止多个线程同时进入锁区后重复创建
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
(4)SpringBoot 中的应用

Spring 容器中的 Bean 默认是单例,底层通过DefaultSingletonBeanRegistry实现,核心逻辑类似 DCL:

// Spring源码核心逻辑(简化)
public class DefaultSingletonBeanRegistry {
    // 存储单例Bean的缓存
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    public Object getSingleton(String beanName) {
        // 先查缓存
        Object singletonObject = singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 加锁创建Bean
            synchronized (this.singletonObjects) {
                singletonObject = singletonObjects.get(beanName);
                if (singletonObject == null) {
                    // 创建Bean实例(后续逻辑)
                    singletonObject = createBean(beanName);
                    singletonObjects.put(beanName, singletonObject);
                }
            }
        }
        return singletonObject;
    }
}

2. 工厂模式:封装对象创建逻辑

(1)核心原理

定义一个创建对象的接口,让子类决定创建哪个类的实例,工厂类负责统一管理创建逻辑。

(2)应用场景
  • 对象创建逻辑复杂(如需要初始化配置、依赖其他对象);
  • 需根据不同条件创建不同对象(如支付方式选择:微信支付、支付宝支付);
  • SpringBoot 中的BeanFactoryApplicationContext都是工厂模式的实现。
(3)实战代码(工厂方法模式)
第一步:定义产品接口(支付方式)
// 支付接口(产品接口)
public interface Payment {
    void pay(double amount);
}
第二步:实现具体产品(微信支付、支付宝支付)
// 微信支付(具体产品)
public class WechatPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("微信支付:" + amount + "元");
    }
}

// 支付宝支付(具体产品)
public class AlipayPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("支付宝支付:" + amount + "元");
    }
}
第三步:定义工厂接口 + 具体工厂
// 支付工厂接口
public interface PaymentFactory {
    Payment createPayment();
}

// 微信支付工厂
public class WechatPaymentFactory implements PaymentFactory {
    @Override
    public Payment createPayment() {
        // 可在此处添加微信支付的初始化逻辑(如配置appId、密钥)
        return new WechatPayment();
    }
}

// 支付宝支付工厂
public class AlipayPaymentFactory implements PaymentFactory {
    @Override
    public Payment createPayment() {
        // 支付宝初始化逻辑
        return new AlipayPayment();
    }
}
第四步:使用工厂创建对象
public class PaymentTest {
    public static void main(String[] args) {
        // 选择微信支付
        PaymentFactory factory = new WechatPaymentFactory();
        Payment payment = factory.createPayment();
        payment.pay(100); // 输出:微信支付:100.0元

        // 切换支付宝支付(无需修改业务逻辑,符合开闭原则)
        factory = new AlipayPaymentFactory();
        payment = factory.createPayment();
        payment.pay(200); // 输出:支付宝支付:200.0元
    }
}
(4)SpringBoot 中的应用

ApplicationContext是 Spring 的核心工厂,负责创建和管理所有 Bean:

// SpringBoot中获取Bean(工厂模式的典型使用)
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 创建Spring容器(工厂)
        ApplicationContext context = SpringApplication.run(Application.class, args);
        // 从工厂获取Bean(产品)
        PaymentService paymentService = context.getBean(PaymentService.class);
        paymentService.processPayment(100);
    }
}

3. 建造者模式:复杂对象的分步构建

(1)核心原理

将复杂对象的构建过程与表示分离,通过分步构建 + 链式调用,创建多属性、多配置的对象。

(2)应用场景
  • 对象属性多(如 10 + 个属性),且部分属性可选;
  • 需保证对象创建后不可变(final 属性);
  • 常见框架:Lombok 的@Builder注解、MyBatis 的SqlSessionFactoryBuilder
(3)实战代码(手动实现建造者模式)
/**
 * 复杂对象:用户订单(含多个必填+可选属性)
 */
public class Order {
    // 必填属性(final,不可变)
    private final String orderId;
    private final String userId;
    private final double totalAmount;

    // 可选属性
    private final String couponCode;
    private final String address;
    private final boolean isExpress;

    // 私有构造器:仅允许Builder调用
    private Order(Builder builder) {
        this.orderId = builder.orderId;
        this.userId = builder.userId;
        this.totalAmount = builder.totalAmount;
        this.couponCode = builder.couponCode;
        this.address = builder.address;
        this.isExpress = builder.isExpress;
    }

    // 建造者类(静态内部类)
    public static class Builder {
        // 必填属性(必须在构造器中传入)
        private final String orderId;
        private final String userId;
        private final double totalAmount;

        // 可选属性(默认值)
        private String couponCode = "";
        private String address = "";
        private boolean isExpress = false;

        // 建造者构造器(传入必填属性)
        public Builder(String orderId, String userId, double totalAmount) {
            this.orderId = orderId;
            this.userId = userId;
            this.totalAmount = totalAmount;
        }

        // 可选属性链式设置
        public Builder couponCode(String couponCode) {
            this.couponCode = couponCode;
            return this; // 返回this,支持链式调用
        }

        public Builder address(String address) {
            this.address = address;
            return this;
        }

        public Builder isExpress(boolean isExpress) {
            this.isExpress = isExpress;
            return this;
        }

        // 构建最终对象
        public Order build() {
            return new Order(this);
        }
    }

    // getter方法(无setter,保证不可变)
    public String getOrderId() { return orderId; }
    // 其他getter...
}
(4)使用建造者创建对象
public class OrderTest {
    public static void main(String[] args) {
        // 链式构建订单(清晰易懂,必填+可选属性分离)
        Order order = new Order.Builder("ORDER_001", "USER_100", 399.9)
                .couponCode("COUPON_50")
                .address("北京市海淀区")
                .isExpress(true)
                .build();

        System.out.println("订单ID:" + order.getOrderId());
        System.out.println("是否加急:" + order.isExpress());
    }
}
(5)SpringBoot 中的应用

Lombok 的@Builder注解可直接生成建造者模式,简化代码:

import lombok.Builder;
import lombok.Data;

@Data // 生成getter、setter、toString等
@Builder // 生成建造者模式
public class Order {
    // 必填属性
    private final String orderId;
    private final String userId;
    private final double totalAmount;

    // 可选属性
    private String couponCode = "";
    private String address = "";
    private boolean isExpress = false;
}

// 使用Lombok生成的建造者
Order order = Order.builder()
        .orderId("ORDER_002")
        .userId("USER_200")
        .totalAmount(599.9)
        .couponCode("COUPON_100")
        .build();

三、结构型模式:如何优化类与对象的组合?

结构型模式的核心是 “优化类 / 对象的组合关系”,在不改变原有代码的前提下,提升系统的灵活性和复用性。

1. 代理模式:给对象找个 “中间人”

(1)核心原理

在不修改目标对象的前提下,通过代理对象控制对目标对象的访问,实现额外功能(如日志、权限、缓存)。

(2)应用场景
  • 日志记录、性能监控(如记录接口调用耗时);
  • 权限校验(如接口访问前验证登录状态);
  • SpringAOP 的底层实现(JDK 动态代理 + CGlib 代理)。
(3)实战代码(JDK 动态代理,SpringAOP 底层)
第一步:定义目标接口(用户服务)
public interface UserService {
    void queryUser(String userId);
}
第二步:实现目标对象(真实用户服务)
public class UserServiceImpl implements UserService {
    @Override
    public void queryUser(String userId) {
        System.out.println("查询用户信息:userId=" + userId);
    }
}
第三步:实现代理处理器(增强逻辑)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;

// 代理处理器:定义增强逻辑(日志+耗时统计)
public class LogInvocationHandler implements InvocationHandler {
    // 目标对象
    private final Object target;

    public LogInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置增强:记录日志和开始时间
        System.out.println("【日志】" + new Date() + " 调用方法:" + method.getName());
        long start = System.currentTimeMillis();

        // 调用目标对象的核心方法
        Object result = method.invoke(target, args);

        // 后置增强:记录耗时
        long end = System.currentTimeMillis();
        System.out.println("【日志】方法执行耗时:" + (end - start) + "ms");

        return result;
    }
}
第四步:生成代理对象并使用
import java.lang.reflect.Proxy;

public class ProxyTest {
    public static void main(String[] args) {
        // 1. 创建目标对象
        UserService userService = new UserServiceImpl();

        // 2. 生成动态代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                new LogInvocationHandler(userService)
        );

        // 3. 通过代理对象调用方法(自动增强)
        proxy.queryUser("USER_100");
    }
}
(4)运行结果
【日志】Thu Oct 12 15:30:00 CST 2023 调用方法:queryUser
查询用户信息:userId=USER_100
【日志】方法执行耗时:2ms
(5)SpringBoot 中的应用(AOP)

SpringAOP 通过代理模式实现切面增强,无需手动写代理类:

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect // 标记为切面
@Component
public class LogAspect {
    // 切点:匹配UserService的所有方法
    @Before("execution(* com.example.service.UserService.*(..))")
    public void before() {
        System.out.println("【AOP前置】记录接口调用日志");
    }

    @After("execution(* com.example.service.UserService.*(..))")
    public void after() {
        System.out.println("【AOP后置】记录接口执行结果");
    }
}

2. 装饰器模式:动态给对象添加功能

(1)核心原理

动态地给一个对象添加额外功能,且不改变其原有结构(比继承更灵活)。

(2)应用场景
  • 给核心功能添加可选增强功能(如 IO 流的缓冲、加密;接口的缓存、降级);
  • 功能组合多样,避免继承导致的类爆炸;
  • JDK 中的BufferedReaderInputStream系列都是装饰器模式。
(3)实战代码(接口缓存装饰器)
第一步:定义核心接口(商品服务)
public interface ProductService {
    String getProductInfo(String productId);
}
第二步:实现核心功能(真实商品服务)
public class ProductServiceImpl implements ProductService {
    @Override
    public String getProductInfo(String productId) {
        // 模拟数据库查询(耗时操作)
        System.out.println("【数据库查询】获取商品信息:productId=" + productId);
        return "商品" + productId + ":手机,价格3999元";
    }
}
第三步:实现装饰器(缓存增强)
import java.util.HashMap;
import java.util.Map;

// 装饰器:实现核心接口,持有目标对象引用
public class CacheProductDecorator implements ProductService {
    // 持有目标对象
    private final ProductService target;
    // 缓存容器
    private final Map<String, String> cache = new HashMap<>();
    // 缓存过期时间(30秒)
    private static final long CACHE_EXPIRE = 30 * 1000;

    public CacheProductDecorator(ProductService target) {
        this.target = target;
    }

    @Override
    public String getProductInfo(String productId) {
        // 1. 先查缓存
        if (cache.containsKey(productId)) {
            System.out.println("【缓存命中】获取商品信息:productId=" + productId);
            return cache.get(productId);
        }

        // 2. 缓存未命中,调用目标对象查询
        String productInfo = target.getProductInfo(productId);

        // 3. 存入缓存(模拟过期时间,实际可用Redis)
        cache.put(productId, productInfo);

        return productInfo;
    }
}
第四步:使用装饰器
public class DecoratorTest {
    public static void main(String[] args) {
        // 1. 创建核心对象
        ProductService productService = new ProductServiceImpl();

        // 2. 用装饰器包装核心对象(添加缓存功能)
        ProductService cacheService = new CacheProductDecorator(productService);

        // 第一次调用:缓存未命中,走数据库
        System.out.println(cacheService.getProductInfo("PROD_001"));

        // 第二次调用:缓存命中,直接返回
        System.out.println(cacheService.getProductInfo("PROD_001"));
    }
}
(4)运行结果
【数据库查询】获取商品信息:productId=PROD_001
商品PROD_001:手机,价格3999元
【缓存命中】获取商品信息:productId=PROD_001
商品PROD_001:手机,价格3999元
(5)JDK 中的应用

BufferedReader装饰FileReader,添加缓冲功能:

// JDK装饰器模式示例
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
    String line = reader.readLine(); // 缓冲读取,提升效率
} catch (Exception e) {
    e.printStackTrace();
}

3. 适配器模式:让不兼容的接口 “牵手”

(1)核心原理

将一个类的接口转换成客户端期望的另一个接口,解决接口不兼容的问题(如旧系统接口适配新系统)。

(2)应用场景
  • 新旧系统集成(旧接口与新接口不兼容);
  • 第三方组件适配(如支付接口、短信接口适配);
  • SpringBoot 中的HandlerAdapter(适配不同的 Controller 方法)。
(3)实战代码(支付接口适配)
第一步:新系统接口(目标接口)
// 新系统统一支付接口
public interface NewPaymentService {
    // 新接口方法:支持订单号+金额+支付方式
    void pay(String orderNo, double amount, String payType);
}
第二步:旧系统接口(待适配接口)
// 旧系统微信支付接口(接口不兼容)
public class OldWechatPayment {
    // 旧接口方法:仅支持订单号+金额
    public void wechatPay(String orderId, double money) {
        System.out.println("旧系统微信支付:订单号=" + orderId + ",金额=" + money);
    }
}
第三步:实现适配器
// 适配器:实现新接口,持有旧接口对象
public class WechatPaymentAdapter implements NewPaymentService {
    // 持有旧接口对象
    private final OldWechatPayment oldWechatPayment;

    public WechatPaymentAdapter(OldWechatPayment oldWechatPayment) {
        this.oldWechatPayment = oldWechatPayment;
    }

    @Override
    public void pay(String orderNo, double amount, String payType) {
        // 适配逻辑:将新接口参数转换为旧接口参数
        if ("WECHAT".equals(payType)) {
            oldWechatPayment.wechatPay(orderNo, amount);
        }
    }
}
第四步:使用适配器
public class AdapterTest {
    public static void main(String[] args) {
        // 1. 旧系统对象
        OldWechatPayment oldPayment = new OldWechatPayment();

        // 2. 适配器包装旧对象
        NewPaymentService newPayment = new WechatPaymentAdapter(oldPayment);

        // 3. 新系统调用统一接口(适配旧系统)
        newPayment.pay("ORDER_003", 299.9, "WECHAT");
    }
}
(4)SpringBoot 中的应用

HandlerAdapter适配不同的 Controller 方法(如 @RequestMapping、@GetMapping):

// SpringBoot源码核心逻辑(简化)
public interface HandlerAdapter {
    boolean supports(Object handler); // 判断是否支持该Controller
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

// 适配@RequestMapping注解的Controller
public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof HandlerMethod && ((HandlerMethod) handler).hasRequestMapping();
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 适配逻辑:将HTTP请求转换为Controller方法参数
        return handleInternal(request, response, (HandlerMethod) handler);
    }
}

四、行为型模式:如何优化对象间的交互?

行为型模式的核心是 “优化对象间的通信”,解耦行为的发起者和接收者。

1. 策略模式:封装多变的算法

(1)核心原理

定义一系列算法,将每个算法封装成独立的类,让它们可以互相替换,且算法的变化不影响使用算法的客户端。

(2)应用场景
  • 业务规则多变(如折扣计算、排序算法、校验规则);
  • 多种支付方式、多种登录方式(如手机号登录、微信登录、QQ 登录);
  • SpringBoot 中的Resource(不同资源加载策略:文件、URL、ClassPath)。
(3)实战代码(折扣计算策略)
第一步:定义策略接口(折扣算法)
public interface DiscountStrategy {
    // 计算折扣后价格
    double calculateDiscount(double originalPrice);
}
第二步:实现具体策略
// 无折扣策略
public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double originalPrice) {
        return originalPrice;
    }
}

// 满减策略(满300减50)
public class FullReduceDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double originalPrice) {
        if (originalPrice >= 300) {
            return originalPrice - 50;
        }
        return originalPrice;
    }
}

// 打折策略(9折)
public class RateDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double originalPrice) {
        return originalPrice * 0.9;
    }
}
第三步:定义上下文(使用策略的客户端)
public class OrderContext {
    // 持有策略对象
    private DiscountStrategy discountStrategy;

    // 构造器注入策略
    public OrderContext(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    // 切换策略
    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    // 计算最终价格
    public double calculateFinalPrice(double originalPrice) {
        return discountStrategy.calculateDiscount(originalPrice);
    }
}
第四步:使用策略模式
public class StrategyTest {
    public static void main(String[] args) {
        double originalPrice = 399.9;

        // 1. 无折扣
        OrderContext order = new OrderContext(new NoDiscountStrategy());
        System.out.println("无折扣价格:" + order.calculateFinalPrice(originalPrice));

        // 2. 切换满减策略
        order.setDiscountStrategy(new FullReduceDiscountStrategy());
        System.out.println("满减后价格:" + order.calculateFinalPrice(originalPrice));

        // 3. 切换打折策略
        order.setDiscountStrategy(new RateDiscountStrategy());
        System.out.println("9折后价格:" + order.calculateFinalPrice(originalPrice));
    }
}
(4)运行结果
无折扣价格:399.9
满减后价格:349.9
9折后价格:359.91

2. 观察者模式:发布 - 订阅式通信

(1)核心原理

定义对象间的一对多依赖关系,当一个对象(被观察者)状态变化时,所有依赖它的对象(观察者)都会收到通知并自动更新。

(2)应用场景
  • 事件通知(如订单支付成功后,通知库存、物流、积分系统);
  • 消息订阅(如公众号推送、消息队列的发布 - 订阅模式);
  • SpringBoot 中的ApplicationEventApplicationListener(事件驱动)。
(3)实战代码(订单支付通知)
第一步:定义事件(被观察者的状态)
// 订单支付事件(被观察者)
public class OrderPaidEvent {
    private final String orderId;
    private final double amount;

    public OrderPaidEvent(String orderId, double amount) {
        this.orderId = orderId;
        this.amount = amount;
    }

    // getter方法
    public String getOrderId() { return orderId; }
    public double getAmount() { return amount; }
}
第二步:定义观察者接口
// 观察者接口
public interface OrderListener {
    void onOrderPaid(OrderPaidEvent event);
}
第三步:实现具体观察者
// 库存观察者:支付成功后扣减库存
public class InventoryListener implements OrderListener {
    @Override
    public void onOrderPaid(OrderPaidEvent event) {
        System.out.println("【库存系统】订单" + event.getOrderId() + "支付成功,扣减库存");
    }
}

// 积分观察者:支付成功后增加积分
public class PointListener implements OrderListener {
    @Override
    public void onOrderPaid(OrderPaidEvent event) {
        int points = (int) event.getAmount(); // 1元=1积分
        System.out.println("【积分系统】订单" + event.getOrderId() + "支付成功,增加" + points + "积分");
    }
}

// 物流观察者:支付成功后创建物流单
public class LogisticsListener implements OrderListener {
    @Override
    public void onOrderPaid(OrderPaidEvent event) {
        System.out.println("【物流系统】订单" + event.getOrderId() + "支付成功,创建物流单");
    }
}
第四步:定义事件发布者(管理观察者)
import java.util.ArrayList;
import java.util.List;

// 事件发布者(被观察者的管理类)
public class OrderEventPublisher {
    // 存储所有观察者
    private final List<OrderListener> listeners = new ArrayList<>();

    // 注册观察者
    public void registerListener(OrderListener listener) {
        listeners.add(listener);
    }

    // 移除观察者
    public void removeListener(OrderListener listener) {
        listeners.remove(listener);
    }

    // 发布事件(通知所有观察者)
    public void publishEvent(OrderPaidEvent event) {
        for (OrderListener listener : listeners) {
            listener.onOrderPaid(event);
        }
    }
}
第五步:使用观察者模式
public class ObserverTest {
    public static void main(String[] args) {
        // 1. 创建事件发布者
        OrderEventPublisher publisher = new OrderEventPublisher();

        // 2. 注册观察者
        publisher.registerListener(new InventoryListener());
        publisher.registerListener(new PointListener());
        publisher.registerListener(new LogisticsListener());

        // 3. 模拟订单支付成功,发布事件
        OrderPaidEvent event = new OrderPaidEvent("ORDER_004", 299.9);
        publisher.publishEvent(event);
    }
}
(4)运行结果
【库存系统】订单ORDER_004支付成功,扣减库存
【积分系统】订单ORDER_004支付成功,增加299积分
【物流系统】订单ORDER_004支付成功,创建物流单
(5)SpringBoot 中的应用

SpringBoot 的事件驱动模型(基于观察者模式):

// 1. 定义事件(继承ApplicationEvent)
public class OrderPaidSpringEvent extends ApplicationEvent {
    private final String orderId;
    private final double amount;

    public OrderPaidSpringEvent(Object source, String orderId, double amount) {
        super(source);
        this.orderId = orderId;
        this.amount = amount;
    }

    // getter...
}

// 2. 定义观察者(实现ApplicationListener)
@Component
public class InventorySpringListener implements ApplicationListener<OrderPaidSpringEvent> {
    @Override
    public void onApplicationEvent(OrderPaidSpringEvent event) {
        System.out.println("【Spring事件】库存系统:订单" + event.getOrderId() + "支付成功");
    }
}

// 3. 发布事件(注入ApplicationEventPublisher)
@Service
public class OrderService {
    private final ApplicationEventPublisher publisher;

    // 构造器注入
    public OrderService(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void payOrder(String orderId, double amount) {
        // 模拟支付逻辑
        System.out.println("订单" + orderId + "支付成功");
        // 发布事件
        publisher.publishEvent(new OrderPaidSpringEvent(this, orderId, amount));
    }
}

五、企业级开发设计模式选型指南

业务场景 推荐设计模式 举例说明
全局唯一对象(工具类、连接池) 单例模式 Spring Bean、Redis 连接池
多类型对象创建(支付、登录) 工厂模式 多种支付方式创建、登录方式选择
复杂对象构建(多属性订单、配置) 建造者模式 订单创建、配置类构建
日志、权限、监控(无侵入增强) 代理模式 Spring AOP、接口权限校验
功能动态增强(缓存、加密) 装饰器模式 IO 流缓冲、接口缓存
新旧系统集成、第三方接口适配 适配器模式 旧支付接口适配新系统
多变业务规则(折扣、排序) 策略模式 多种折扣计算、排序算法选择
事件通知、发布订阅 观察者模式 订单支付后多系统通知

六、总结

设计模式不是 “银弹”,没有最好的模式,只有最适合的场景。学习设计模式的核心,不是死记硬背模板,而是理解其 “解耦、复用、扩展” 的设计思想。

在企业级开发中,我们不需要刻意追求 “用遍所有模式”,而是在遇到特定问题时,能想到对应的模式解决方案。比如:

  • 想避免重复创建对象 → 用单例模式;
  • 想给接口加日志但不想改原有代码 → 用代理模式;
  • 想让不同系统解耦通信 → 用观察者模式。

同时,SpringBoot 等框架已经帮我们封装了大量设计模式,理解这些模式的底层实现,能让你更深入地掌握框架的使用技巧(如 AOP、事件驱动)。

希望这篇文章能带你从 “知道设计模式” 到 “会用设计模式”,在实际项目中写出更优雅、更易维护的代码!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐