设计模式是前辈们总结的代码设计经验,是解决特定场景问题的 “最优解模板”。在 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 中的BeanFactory、ApplicationContext都是工厂模式的实现。
(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 中的BufferedReader、InputStream系列都是装饰器模式。
(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 中的ApplicationEvent和ApplicationListener(事件驱动)。
(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编程工具,助力开发者即刻编程。

更多推荐