Skip to content

设计模式 ​

GoF 23 种设计模式在 Java 中的经典实现。

设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类编目的代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。


一、设计模式概述 ​

1.1 什么是设计模式 ​

设计模式描述了在软件设计过程中针对特定场景的、可重复使用的解决方案。1995 年,GoF(Gang of Four,四人组)出版了《Design Patterns: Elements of Reusable Object-Oriented Software》,定义了 23 种经典设计模式。

1.2 模式的分类 ​

设计模式按目的分为三大类:

类别关注点包含模式
创建型模式对象的创建过程单例、工厂方法、抽象工厂、建造者、原型
结构型模式类和对象的组合代理、适配器、装饰器、外观、组合、桥接、享元
行为型模式对象之间的通信策略、模板方法、观察者、责任链、命令、状态、迭代器、访问者、中介者、备忘录、解释器

1.3 六大设计原则(SOLID + 最少知识原则) ​

在设计模式中,面向对象设计原则是基石。以下是六个核心原则:

缩写原则名称核心思想
S单一职责原则(SRP)一个类只有一个引起它变化的原因
O开闭原则(OCP)对扩展开放,对修改关闭
L里氏替换原则(LSP)子类必须能替换父类
I接口隔离原则(ISP)接口应该小而专,不强迫依赖不需要的方法
D依赖倒置原则(DIP)面向接口编程,不依赖具体实现
LoD最少知识原则(迪米特法则)一个对象应尽可能少地了解其他对象

单一职责原则(SRP)

java
// 反例:一个类负责多个职责
public class UserService {
    public void saveUser(User user) { /* 数据持久化 */ }
    public void sendEmail(User user) { /* 发送邮件 */ }
    public void generateReport(User user) { /* 生成报表 */ }
}

// 正例:拆分职责
public class UserService {
    public void saveUser(User user) { /* 数据持久化 */ }
}
public class EmailService {
    public void sendEmail(User user) { /* 发送邮件 */ }
}
public class ReportService {
    public void generateReport(User user) { /* 生成报表 */ }
}
// 反例:一个类负责多个职责
public class UserService {
    public void saveUser(User user) { /* 数据持久化 */ }
    public void sendEmail(User user) { /* 发送邮件 */ }
    public void generateReport(User user) { /* 生成报表 */ }
}

// 正例:拆分职责
public class UserService {
    public void saveUser(User user) { /* 数据持久化 */ }
}
public class EmailService {
    public void sendEmail(User user) { /* 发送邮件 */ }
}
public class ReportService {
    public void generateReport(User user) { /* 生成报表 */ }
}

开闭原则(OCP)

java
// 对扩展开放,对修改关闭
public interface Shape {
    double area();
}

public class Rectangle implements Shape {
    private double width, height;
    public double area() { return width * height; }
}

public class Circle implements Shape {
    private double radius;
    public double area() { return Math.PI * radius * radius; }
}
// 新增三角形不需要修改现有代码,只需实现 Shape 接口
// 对扩展开放,对修改关闭
public interface Shape {
    double area();
}

public class Rectangle implements Shape {
    private double width, height;
    public double area() { return width * height; }
}

public class Circle implements Shape {
    private double radius;
    public double area() { return Math.PI * radius * radius; }
}
// 新增三角形不需要修改现有代码,只需实现 Shape 接口

依赖倒置原则(DIP)

java
// 高层模块不依赖低层模块,二者都依赖抽象
public interface Database {
    void save(Object obj);
}

public class MySQLDatabase implements Database {
    public void save(Object obj) { /* MySQL 保存 */ }
}

public class UserService {
    private Database database; // 依赖抽象,不依赖具体实现
    public UserService(Database database) {
        this.database = database;
    }
}
// 高层模块不依赖低层模块,二者都依赖抽象
public interface Database {
    void save(Object obj);
}

public class MySQLDatabase implements Database {
    public void save(Object obj) { /* MySQL 保存 */ }
}

public class UserService {
    private Database database; // 依赖抽象,不依赖具体实现
    public UserService(Database database) {
        this.database = database;
    }
}

二、创建型模式(Creational Patterns) ​

创建型模式关注对象的创建机制,将对象的创建与使用分离,使系统在创建对象时更加灵活。


2.1 单例模式(Singleton Pattern) ​

定义:确保一个类只有一个实例,并提供一个全局访问点。

单例模式是 Java 中使用最广泛的设计模式之一,也是面试考查的重点。

2.1.1 饿汉式(Eager Initialization) ​

java
public class SingletonEager {
    private static final SingletonEager INSTANCE = new SingletonEager();

    private SingletonEager() {}

    public static SingletonEager getInstance() {
        return INSTANCE;
    }
}
public class SingletonEager {
    private static final SingletonEager INSTANCE = new SingletonEager();

    private SingletonEager() {}

    public static SingletonEager getInstance() {
        return INSTANCE;
    }
}
  • 优点:线程安全,实现简单
  • 缺点:类加载时就创建实例,可能造成资源浪费

2.1.2 懒汉式(Lazy Initialization) ​

java
public class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {}

    public static synchronized SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}
public class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {}

    public static synchronized SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}
  • 优点:延迟加载,需要时才创建
  • 缺点:synchronized 加在方法上,性能较差

2.1.3 DCL(双重检查锁,Double-Checked Locking) ​

java
public class SingletonDCL {
    private static volatile SingletonDCL instance;

    private SingletonDCL() {}

    public static SingletonDCL getInstance() {
        if (instance == null) {                // 第一次检查
            synchronized (SingletonDCL.class) {
                if (instance == null) {        // 第二次检查
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}
public class SingletonDCL {
    private static volatile SingletonDCL instance;

    private SingletonDCL() {}

    public static SingletonDCL getInstance() {
        if (instance == null) {                // 第一次检查
            synchronized (SingletonDCL.class) {
                if (instance == null) {        // 第二次检查
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}
  • volatile 关键字:禁止指令重排序,保证可见性
  • 双重检查:只在第一次创建时进入同步块,后续直接返回

2.1.4 静态内部类(Static Inner Class / Holder Pattern) ​

java
public class SingletonHolder {
    private SingletonHolder() {}

    private static class Holder {
        private static final SingletonHolder INSTANCE = new SingletonHolder();
    }

    public static SingletonHolder getInstance() {
        return Holder.INSTANCE;
    }
}
public class SingletonHolder {
    private SingletonHolder() {}

    private static class Holder {
        private static final SingletonHolder INSTANCE = new SingletonHolder();
    }

    public static SingletonHolder getInstance() {
        return Holder.INSTANCE;
    }
}
  • 原理:JVM 在加载静态内部类时才会创建实例,既实现了延迟加载,又保证了线程安全
  • 优点:最推荐的实现方式之一,性能高

2.1.5 枚举单例(Enum Singleton) ​

java
public enum SingletonEnum {
    INSTANCE;

    public void doSomething() {
        // 业务方法
    }
}
public enum SingletonEnum {
    INSTANCE;

    public void doSomething() {
        // 业务方法
    }
}
  • 优点:
    • 线程安全,JVM 保证
    • 天然防止反射破坏
    • 天然防止序列化破坏
    • 简洁
  • 推荐:Effective Java 作者 Joshua Bloch 推荐的方式

2.1.6 防止反射和序列化破坏 ​

防止反射破坏:

java
public class SingletonSafe {
    private static final SingletonSafe INSTANCE = new SingletonSafe();

    private SingletonSafe() {
        // 防止反射调用
        if (INSTANCE != null) {
            throw new RuntimeException("不允许通过反射创建实例");
        }
    }

    public static SingletonSafe getInstance() {
        return INSTANCE;
    }
}
public class SingletonSafe {
    private static final SingletonSafe INSTANCE = new SingletonSafe();

    private SingletonSafe() {
        // 防止反射调用
        if (INSTANCE != null) {
            throw new RuntimeException("不允许通过反射创建实例");
        }
    }

    public static SingletonSafe getInstance() {
        return INSTANCE;
    }
}

防止序列化破坏:

java
import java.io.Serializable;

public class SingletonSerializable implements Serializable {
    private static final SingletonSerializable INSTANCE = new SingletonSerializable();

    private SingletonSerializable() {}

    public static SingletonSerializable getInstance() {
        return INSTANCE;
    }

    // 实现 readResolve 方法,返回已有的实例
    private Object readResolve() {
        return INSTANCE;
    }
}
import java.io.Serializable;

public class SingletonSerializable implements Serializable {
    private static final SingletonSerializable INSTANCE = new SingletonSerializable();

    private SingletonSerializable() {}

    public static SingletonSerializable getInstance() {
        return INSTANCE;
    }

    // 实现 readResolve 方法,返回已有的实例
    private Object readResolve() {
        return INSTANCE;
    }
}

2.1.7 Spring Bean 中的单例 ​

Spring 容器中 Bean 的默认作用域为 singleton,但 Spring 的单例与 GoF 的单例不同:

  • Scope 为 singleton:每个 Spring IoC 容器中只有一个 Bean 实例
  • 底层实现:Spring 通过容器级别的 Map 缓存来保证单例,而非通过类的静态属性
  • 同一个类可以在 Spring 容器中被多次声明为不同的 Bean
java
@Component
@Scope("singleton") // 默认就是 singleton
public class MyService {
    // Spring 容器中只有这个 Bean 的一个实例
}
@Component
@Scope("singleton") // 默认就是 singleton
public class MyService {
    // Spring 容器中只有这个 Bean 的一个实例
}

2.2 工厂模式(Factory Pattern) ​

2.2.1 简单工厂(Simple Factory / 静态工厂) ​

java
public interface Product {
    void use();
}

public class ConcreteProductA implements Product {
    public void use() { System.out.println("Product A"); }
}

public class ConcreteProductB implements Product {
    public void use() { System.out.println("Product B"); }
}

// 简单工厂
public class SimpleFactory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A": return new ConcreteProductA();
            case "B": return new ConcreteProductB();
            default: throw new IllegalArgumentException("Unknown type: " + type);
        }
    }
}
public interface Product {
    void use();
}

public class ConcreteProductA implements Product {
    public void use() { System.out.println("Product A"); }
}

public class ConcreteProductB implements Product {
    public void use() { System.out.println("Product B"); }
}

// 简单工厂
public class SimpleFactory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A": return new ConcreteProductA();
            case "B": return new ConcreteProductB();
            default: throw new IllegalArgumentException("Unknown type: " + type);
        }
    }
}

注意:简单工厂不是 GoF 23 种设计模式之一,但很常用。

2.2.2 工厂方法(Factory Method) ​

java
// 抽象工厂
public interface Factory {
    Product createProduct();
}

// 具体工厂 A
public class FactoryA implements Factory {
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂 B
public class FactoryB implements Factory {
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 使用
Factory factory = new FactoryA();
Product product = factory.createProduct();
// 抽象工厂
public interface Factory {
    Product createProduct();
}

// 具体工厂 A
public class FactoryA implements Factory {
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂 B
public class FactoryB implements Factory {
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 使用
Factory factory = new FactoryA();
Product product = factory.createProduct();
  • 适用场景:当一个类不知道它需要创建哪个具体类的对象时
  • 优点:符合开闭原则,增加新产品无需修改现有工厂类

2.2.3 抽象工厂(Abstract Factory) ​

java
// 产品族:一个工厂可以生产多个产品
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

public class ConcreteFactory1 implements AbstractFactory {
    public ProductA createProductA() { return new ProductA1(); }
    public ProductB createProductB() { return new ProductB1(); }
}

public class ConcreteFactory2 implements AbstractFactory {
    public ProductA createProductA() { return new ProductA2(); }
    public ProductB createProductB() { return new ProductB2(); }
}
// 产品族:一个工厂可以生产多个产品
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

public class ConcreteFactory1 implements AbstractFactory {
    public ProductA createProductA() { return new ProductA1(); }
    public ProductB createProductB() { return new ProductB1(); }
}

public class ConcreteFactory2 implements AbstractFactory {
    public ProductA createProductA() { return new ProductA2(); }
    public ProductB createProductB() { return new ProductB2(); }
}
  • 适用场景:系统需要创建一组相关或相互依赖的对象(产品族)
  • 与工厂方法的区别:工厂方法针对单一产品等级结构,抽象工厂针对多个产品等级结构

2.2.4 Spring 中的工厂模式 ​

Spring 的 BeanFactory 是工厂模式的经典体现:

java
// BeanFactory 是抽象工厂
BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = factory.getBean("userService", UserService.class);
// BeanFactory 是抽象工厂
BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = factory.getBean("userService", UserService.class);
  • BeanFactory:顶层接口,定义了获取 Bean 的方法
  • ApplicationContext:高级容器,扩展了 BeanFactory
  • FactoryBean:允许用户自定义创建 Bean 的逻辑

2.3 建造者模式(Builder Pattern) ​

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

java
public class Computer {
    private String cpu;
    private String ram;
    private String storage;
    private boolean hasBluetooth;
    private boolean hasWifi;

    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.hasBluetooth = builder.hasBluetooth;
        this.hasWifi = builder.hasWifi;
    }

    // 静态内部 Builder 类
    public static class Builder {
        private String cpu;
        private String ram;
        private String storage;
        private boolean hasBluetooth;
        private boolean hasWifi;

        public Builder cpu(String cpu) { this.cpu = cpu; return this; }
        public Builder ram(String ram) { this.ram = ram; return this; }
        public Builder storage(String storage) { this.storage = storage; return this; }
        public Builder bluetooth(boolean hasBluetooth) { this.hasBluetooth = hasBluetooth; return this; }
        public Builder wifi(boolean hasWifi) { this.hasWifi = hasWifi; return this; }

        public Computer build() {
            return new Computer(this);
        }
    }
}

// 链式调用
Computer computer = new Computer.Builder()
        .cpu("Intel i7")
        .ram("16GB")
        .storage("512GB SSD")
        .bluetooth(true)
        .wifi(true)
        .build();
public class Computer {
    private String cpu;
    private String ram;
    private String storage;
    private boolean hasBluetooth;
    private boolean hasWifi;

    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.hasBluetooth = builder.hasBluetooth;
        this.hasWifi = builder.hasWifi;
    }

    // 静态内部 Builder 类
    public static class Builder {
        private String cpu;
        private String ram;
        private String storage;
        private boolean hasBluetooth;
        private boolean hasWifi;

        public Builder cpu(String cpu) { this.cpu = cpu; return this; }
        public Builder ram(String ram) { this.ram = ram; return this; }
        public Builder storage(String storage) { this.storage = storage; return this; }
        public Builder bluetooth(boolean hasBluetooth) { this.hasBluetooth = hasBluetooth; return this; }
        public Builder wifi(boolean hasWifi) { this.hasWifi = hasWifi; return this; }

        public Computer build() {
            return new Computer(this);
        }
    }
}

// 链式调用
Computer computer = new Computer.Builder()
        .cpu("Intel i7")
        .ram("16GB")
        .storage("512GB SSD")
        .bluetooth(true)
        .wifi(true)
        .build();

Lombok @Builder 注解:

java
import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class User {
    private String name;
    private int age;
    private String email;
    private String phone;
}

// 使用
User user = User.builder()
        .name("张三")
        .age(25)
        .email("zhangsan@example.com")
        .build();
import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class User {
    private String name;
    private int age;
    private String email;
    private String phone;
}

// 使用
User user = User.builder()
        .name("张三")
        .age(25)
        .email("zhangsan@example.com")
        .build();
  • 适用场景:对象构造参数多且复杂,需要灵活的构建过程
  • 优点:链式调用代码可读性好;将构建过程与表现分离

2.4 原型模式(Prototype Pattern) ​

定义:通过复制已有对象来创建新对象,而不是通过 new 创建。

java
public class Prototype implements Cloneable {
    private String name;
    private List<String> tags;

    public Prototype(String name, List<String> tags) {
        this.name = name;
        this.tags = tags;
    }

    // 浅拷贝
    @Override
    protected Prototype clone() throws CloneNotSupportedException {
        return (Prototype) super.clone();
    }

    // 深拷贝
    public Prototype deepClone() {
        Prototype p = new Prototype(this.name, new ArrayList<>(this.tags));
        return p;
    }
}
public class Prototype implements Cloneable {
    private String name;
    private List<String> tags;

    public Prototype(String name, List<String> tags) {
        this.name = name;
        this.tags = tags;
    }

    // 浅拷贝
    @Override
    protected Prototype clone() throws CloneNotSupportedException {
        return (Prototype) super.clone();
    }

    // 深拷贝
    public Prototype deepClone() {
        Prototype p = new Prototype(this.name, new ArrayList<>(this.tags));
        return p;
    }
}

浅拷贝 vs 深拷贝:

对比项浅拷贝深拷贝
基本类型复制值复制值
引用类型复制引用(指向同一对象)创建新对象
实现方式super.clone()序列化 / new / 手动复制
性能高较低

深拷贝的序列化方式:

java
public class DeepClonePrototype implements Serializable {
    private String name;
    private List<String> tags;

    public DeepClonePrototype deepClone() {
        try {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (DeepClonePrototype) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
public class DeepClonePrototype implements Serializable {
    private String name;
    private List<String> tags;

    public DeepClonePrototype deepClone() {
        try {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (DeepClonePrototype) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  • 适用场景:创建对象成本较大(如数据库查询),且对象之间差异不大
  • Java 中:必须实现 Cloneable 接口(标记接口),重写 clone() 方法

三、结构型模式(Structural Patterns) ​

结构型模式关注类和对象的组合,通过继承或组合来构建更大的结构。


3.1 代理模式(Proxy Pattern) ​

定义:为其他对象提供一种代理以控制对这个对象的访问。代理模式是 AOP 的底层实现基础,也是面试重点。

3.1.1 静态代理 ​

通过组合或继承实现,代理类在编译期就已经确定。

java
// 接口
public interface UserService {
    void saveUser(User user);
}

// 目标类
public class UserServiceImpl implements UserService {
    public void saveUser(User user) {
        System.out.println("保存用户: " + user.getName());
    }
}

// 静态代理类(组合方式)
public class UserServiceProxy implements UserService {
    private UserService target;

    public UserServiceProxy(UserService target) {
        this.target = target;
    }

    public void saveUser(User user) {
        System.out.println("前置处理:权限检查");
        target.saveUser(user);
        System.out.println("后置处理:记录日志");
    }
}
// 接口
public interface UserService {
    void saveUser(User user);
}

// 目标类
public class UserServiceImpl implements UserService {
    public void saveUser(User user) {
        System.out.println("保存用户: " + user.getName());
    }
}

// 静态代理类(组合方式)
public class UserServiceProxy implements UserService {
    private UserService target;

    public UserServiceProxy(UserService target) {
        this.target = target;
    }

    public void saveUser(User user) {
        System.out.println("前置处理:权限检查");
        target.saveUser(user);
        System.out.println("后置处理:记录日志");
    }
}
  • 优点:实现简单
  • 缺点:每个目标类需要单独编写代理类,代理类数量膨胀

3.1.2 JDK 动态代理 ​

在运行时动态创建代理对象,要求目标类必须实现接口。

java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxyHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK 动态代理 - 前置处理");
        Object result = method.invoke(target, args);
        System.out.println("JDK 动态代理 - 后置处理");
        return result;
    }

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new JdkProxyHandler(target)
        );
    }
}

// 使用
UserService proxy = JdkProxyHandler.createProxy(new UserServiceImpl());
proxy.saveUser(user);
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxyHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK 动态代理 - 前置处理");
        Object result = method.invoke(target, args);
        System.out.println("JDK 动态代理 - 后置处理");
        return result;
    }

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new JdkProxyHandler(target)
        );
    }
}

// 使用
UserService proxy = JdkProxyHandler.createProxy(new UserServiceImpl());
proxy.saveUser(user);

核心 API:

  • java.lang.reflect.Proxy:创建代理类
  • java.lang.reflect.InvocationHandler:调用处理器接口

3.1.3 CGLIB 动态代理 ​

通过继承目标类创建子类作为代理,不需要接口。

java
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibProxyInterceptor implements MethodInterceptor {
    private Object target;

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

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CGLIB 动态代理 - 前置处理");
        Object result = proxy.invoke(target, args); // 调用目标对象
        System.out.println("CGLIB 动态代理 - 后置处理");
        return result;
    }

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new CglibProxyInterceptor(target));
        return (T) enhancer.create();
    }
}

// 使用(不需要接口)
UserServiceImpl proxy = CglibProxyInterceptor.createProxy(new UserServiceImpl());
proxy.saveUser(user);
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibProxyInterceptor implements MethodInterceptor {
    private Object target;

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

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CGLIB 动态代理 - 前置处理");
        Object result = proxy.invoke(target, args); // 调用目标对象
        System.out.println("CGLIB 动态代理 - 后置处理");
        return result;
    }

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new CglibProxyInterceptor(target));
        return (T) enhancer.create();
    }
}

// 使用(不需要接口)
UserServiceImpl proxy = CglibProxyInterceptor.createProxy(new UserServiceImpl());
proxy.saveUser(user);

核心 API:

  • net.sf.cglib.proxy.Enhancer:字节码增强器
  • net.sf.cglib.proxy.MethodInterceptor:方法拦截器

3.1.4 JDK 动态代理 vs CGLIB 动态代理 ​

对比项JDK 动态代理CGLIB 动态代理
原理基于接口,生成实现类的代理基于继承,生成子类
要求目标类必须实现接口目标类不能是 final 的
实现方式InvocationHandler + ProxyMethodInterceptor + Enhancer
性能创建代理对象快,调用方法慢创建代理对象慢,调用方法快
依赖JDK 自带需要引入 cglib 依赖(Spring 已内置)

3.1.5 Spring AOP 代理选择策略 ​

java
// Spring AOP 底层自动判断使用哪种代理
@Aspect
@Component
public class LogAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice() {
        System.out.println("方法执行前");
    }
}
// Spring AOP 底层自动判断使用哪种代理
@Aspect
@Component
public class LogAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice() {
        System.out.println("方法执行前");
    }
}

Spring AOP 的代理选择逻辑:

  1. 目标类实现了接口:默认使用 JDK 动态代理
  2. 目标类没有实现接口:使用 CGLIB 动态代理
  3. 强制使用 CGLIB:配置 spring.aop.proxy-target-class=true
  4. Spring Boot 2.0+ 默认使用 CGLIB 代理

3.2 适配器模式(Adapter Pattern) ​

定义:将一个类的接口转换成客户希望的另一个接口,使原来不兼容的类可以协同工作。

3.2.1 类适配器(基于继承) ​

java
// 目标接口
public interface Target {
    void request();
}

// 被适配者
public class Adaptee {
    public void specificRequest() {
        System.out.println("特殊请求");
    }
}

// 适配器(继承被适配者)
public class ClassAdapter extends Adaptee implements Target {
    public void request() {
        specificRequest(); // 调用被适配者的方法
    }
}
// 目标接口
public interface Target {
    void request();
}

// 被适配者
public class Adaptee {
    public void specificRequest() {
        System.out.println("特殊请求");
    }
}

// 适配器(继承被适配者)
public class ClassAdapter extends Adaptee implements Target {
    public void request() {
        specificRequest(); // 调用被适配者的方法
    }
}

3.2.2 对象适配器(基于组合) ​

java
// 适配器(持有被适配者的引用,推荐方式)
public class ObjectAdapter implements Target {
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void request() {
        adaptee.specificRequest();
    }
}
// 适配器(持有被适配者的引用,推荐方式)
public class ObjectAdapter implements Target {
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void request() {
        adaptee.specificRequest();
    }
}

3.2.3 Spring MVC HandlerAdapter ​

Spring MVC 使用适配器模式来统一处理不同类型的控制器:

java
// HandlerAdapter 接口(适配器)
public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

// SimpleControllerHandlerAdapter:适配实现了 Controller 接口的处理器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    public boolean supports(Object handler) {
        return (handler instanceof Controller);
    }
    public ModelAndView handle(...) {
        return ((Controller) handler).handleRequest(request, response);
    }
}

// HttpRequestHandlerAdapter:适配实现了 HttpRequestHandler 的处理器
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    public boolean supports(Object handler) {
        return (handler instanceof HttpRequestHandler);
    }
    public ModelAndView handle(...) {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
    }
}
// HandlerAdapter 接口(适配器)
public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

// SimpleControllerHandlerAdapter:适配实现了 Controller 接口的处理器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    public boolean supports(Object handler) {
        return (handler instanceof Controller);
    }
    public ModelAndView handle(...) {
        return ((Controller) handler).handleRequest(request, response);
    }
}

// HttpRequestHandlerAdapter:适配实现了 HttpRequestHandler 的处理器
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    public boolean supports(Object handler) {
        return (handler instanceof HttpRequestHandler);
    }
    public ModelAndView handle(...) {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
    }
}

3.3 装饰器模式(Decorator Pattern) ​

定义:动态地给一个对象添加额外的职责,比继承更加灵活。

3.3.1 Java IO InputStream 体系 ​

装饰器模式在 Java IO 中有着经典应用:

java
InputStream inputStream = new BufferedInputStream(    // 装饰:提供缓冲功能
        new DataInputStream(                           // 装饰:提供基本数据类型的读取
                new FileInputStream("test.txt")        // 被装饰者
        )
);
InputStream inputStream = new BufferedInputStream(    // 装饰:提供缓冲功能
        new DataInputStream(                           // 装饰:提供基本数据类型的读取
                new FileInputStream("test.txt")        // 被装饰者
        )
);

InputStream 体系中的角色:

角色类名说明
抽象组件InputStream顶级抽象类
具体组件FileInputStream被装饰的原始对象
抽象装饰器FilterInputStream装饰器基类
具体装饰器BufferedInputStream提供缓冲功能
具体装饰器DataInputStream提供基本数据类型读取
具体装饰器PushbackInputStream提供回退功能

3.3.2 自定义装饰器示例 ​

java
// 抽象组件
public interface Coffee {
    double cost();
    String description();
}

// 具体组件
public class SimpleCoffee implements Coffee {
    public double cost() { return 10.0; }
    public String description() { return "普通咖啡"; }
}

// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    public double cost() { return coffee.cost(); }
    public String description() { return coffee.description(); }
}

// 具体装饰器
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) { super(coffee); }
    public double cost() { return coffee.cost() + 3.0; }
    public String description() { return coffee.description() + " + 牛奶"; }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) { super(coffee); }
    public double cost() { return coffee.cost() + 1.0; }
    public String description() { return coffee.description() + " + 糖"; }
}

// 使用
Coffee coffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));
System.out.println(coffee.description() + " = " + coffee.cost() + "元");
// 输出:普通咖啡 + 牛奶 + 糖 = 14.0元
// 抽象组件
public interface Coffee {
    double cost();
    String description();
}

// 具体组件
public class SimpleCoffee implements Coffee {
    public double cost() { return 10.0; }
    public String description() { return "普通咖啡"; }
}

// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    public double cost() { return coffee.cost(); }
    public String description() { return coffee.description(); }
}

// 具体装饰器
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) { super(coffee); }
    public double cost() { return coffee.cost() + 3.0; }
    public String description() { return coffee.description() + " + 牛奶"; }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) { super(coffee); }
    public double cost() { return coffee.cost() + 1.0; }
    public String description() { return coffee.description() + " + 糖"; }
}

// 使用
Coffee coffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));
System.out.println(coffee.description() + " = " + coffee.cost() + "元");
// 输出:普通咖啡 + 牛奶 + 糖 = 14.0元

3.3.3 装饰器 vs 继承 ​

对比项装饰器模式继承
扩展方式动态组合静态编译
增减功能灵活运行时增减需创建新子类
类数量避免类爆炸功能组合多时产生大量子类
客户端透明客户端无需感知装饰过程客户端需知道具体子类

3.4 外观模式(Facade Pattern) ​

定义:为子系统中的一组接口提供一个统一的接口,定义一个高层接口让子系统更容易使用。

java
// 子系统类
public class CPU {
    public void start() { System.out.println("CPU 启动"); }
}
public class Memory {
    public void load() { System.out.println("内存加载"); }
}
public class HardDrive {
    public void read() { System.out.println("硬盘读取"); }
}

// 外观类
public class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    public void start() {
        cpu.start();
        memory.load();
        hardDrive.read();
        System.out.println("计算机启动完成");
    }
}

// 客户端调用
ComputerFacade computer = new ComputerFacade();
computer.start(); // 一个调用完成所有启动步骤
// 子系统类
public class CPU {
    public void start() { System.out.println("CPU 启动"); }
}
public class Memory {
    public void load() { System.out.println("内存加载"); }
}
public class HardDrive {
    public void read() { System.out.println("硬盘读取"); }
}

// 外观类
public class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    public void start() {
        cpu.start();
        memory.load();
        hardDrive.read();
        System.out.println("计算机启动完成");
    }
}

// 客户端调用
ComputerFacade computer = new ComputerFacade();
computer.start(); // 一个调用完成所有启动步骤
  • 适用场景:为复杂子系统提供简化接口,分层系统中的 Service 层
  • 优点:减少系统耦合、提高易用性

3.5 组合模式(Composite Pattern) ​

定义:将对象组合成树形结构以表示"部分-整体"的层次结构,使客户端对单个对象和组合对象的使用具有一致性。

java
// 抽象组件
public interface FileComponent {
    void show();
    long getSize();
}

// 叶子节点:文件
public class FileLeaf implements FileComponent {
    private String name;
    private long size;

    public FileLeaf(String name, long size) {
        this.name = name;
        this.size = size;
    }

    public void show() { System.out.println("文件: " + name); }
    public long getSize() { return size; }
}

// 组合节点:文件夹
public class FolderComposite implements FileComponent {
    private String name;
    private List<FileComponent> children = new ArrayList<>();

    public FolderComposite(String name) { this.name = name; }

    public void add(FileComponent component) { children.add(component); }
    public void remove(FileComponent component) { children.remove(component); }

    public void show() {
        System.out.println("文件夹: " + name);
        for (FileComponent child : children) {
            child.show();
        }
    }

    public long getSize() {
        long total = 0;
        for (FileComponent child : children) {
            total += child.getSize();
        }
        return total;
    }
}
// 抽象组件
public interface FileComponent {
    void show();
    long getSize();
}

// 叶子节点:文件
public class FileLeaf implements FileComponent {
    private String name;
    private long size;

    public FileLeaf(String name, long size) {
        this.name = name;
        this.size = size;
    }

    public void show() { System.out.println("文件: " + name); }
    public long getSize() { return size; }
}

// 组合节点:文件夹
public class FolderComposite implements FileComponent {
    private String name;
    private List<FileComponent> children = new ArrayList<>();

    public FolderComposite(String name) { this.name = name; }

    public void add(FileComponent component) { children.add(component); }
    public void remove(FileComponent component) { children.remove(component); }

    public void show() {
        System.out.println("文件夹: " + name);
        for (FileComponent child : children) {
            child.show();
        }
    }

    public long getSize() {
        long total = 0;
        for (FileComponent child : children) {
            total += child.getSize();
        }
        return total;
    }
}
  • 适用场景:树形菜单、文件系统、组织架构等树形结构
  • 透明方式 vs 安全方式:透明方式将管理方法放在抽象组件中,安全方式将管理方法放在组合节点中

3.6 桥接模式(Bridge Pattern) ​

定义:将抽象部分与实现部分分离,使它们可以独立地变化。

java
// 实现接口
public interface DrawAPI {
    void drawCircle(int x, int y, int radius);
}

// 具体实现 A
public class RedDraw implements DrawAPI {
    public void drawCircle(int x, int y, int radius) {
        System.out.println("画红色圆,坐标(" + x + "," + y + "),半径" + radius);
    }
}

// 具体实现 B
public class BlueDraw implements DrawAPI {
    public void drawCircle(int x, int y, int radius) {
        System.out.println("画蓝色圆,坐标(" + x + "," + y + "),半径" + radius);
    }
}

// 抽象类
public abstract class Shape {
    protected DrawAPI drawAPI;

    protected Shape(DrawAPI drawAPI) {
        this.drawAPI = drawAPI;
    }

    public abstract void draw();
}

// 扩展抽象类
public class Circle extends Shape {
    private int x, y, radius;

    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x; this.y = y; this.radius = radius;
    }

    public void draw() {
        drawAPI.drawCircle(x, y, radius);
    }
}
// 实现接口
public interface DrawAPI {
    void drawCircle(int x, int y, int radius);
}

// 具体实现 A
public class RedDraw implements DrawAPI {
    public void drawCircle(int x, int y, int radius) {
        System.out.println("画红色圆,坐标(" + x + "," + y + "),半径" + radius);
    }
}

// 具体实现 B
public class BlueDraw implements DrawAPI {
    public void drawCircle(int x, int y, int radius) {
        System.out.println("画蓝色圆,坐标(" + x + "," + y + "),半径" + radius);
    }
}

// 抽象类
public abstract class Shape {
    protected DrawAPI drawAPI;

    protected Shape(DrawAPI drawAPI) {
        this.drawAPI = drawAPI;
    }

    public abstract void draw();
}

// 扩展抽象类
public class Circle extends Shape {
    private int x, y, radius;

    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x; this.y = y; this.radius = radius;
    }

    public void draw() {
        drawAPI.drawCircle(x, y, radius);
    }
}

JDBC DriverManager 中的桥接模式:

java
// Driver 是桥接中的"实现"接口
// DriverManager 是桥接中的"抽象"
// 不同数据库驱动(MySQL、Oracle)是具体实现

// 客户端只需要面向 JDBC 接口编程
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db");
// 底层实际调用 MySQL 驱动或 Oracle 驱动
// Driver 是桥接中的"实现"接口
// DriverManager 是桥接中的"抽象"
// 不同数据库驱动(MySQL、Oracle)是具体实现

// 客户端只需要面向 JDBC 接口编程
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db");
// 底层实际调用 MySQL 驱动或 Oracle 驱动

3.7 享元模式(Flyweight Pattern) ​

定义:运用共享技术有效地支持大量细粒度的对象。

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

// 具体享元
public class ConcreteFlyweight implements Flyweight {
    private String intrinsicState; // 内部状态(可共享)

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

    public void operate(String extrinsicState) { // 外部状态(不可共享)
        System.out.println("内部状态: " + intrinsicState + ", 外部状态: " + extrinsicState);
    }
}

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

    public static Flyweight getFlyweight(String key) {
        Flyweight flyweight = pool.get(key);
        if (flyweight == null) {
            flyweight = new ConcreteFlyweight(key);
            pool.put(key, flyweight);
        }
        return flyweight;
    }
}
// 享元接口
public interface Flyweight {
    void operate(String extrinsicState);
}

// 具体享元
public class ConcreteFlyweight implements Flyweight {
    private String intrinsicState; // 内部状态(可共享)

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

    public void operate(String extrinsicState) { // 外部状态(不可共享)
        System.out.println("内部状态: " + intrinsicState + ", 外部状态: " + extrinsicState);
    }
}

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

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

Java 中的享元模式应用:

  • String 常量池:相同的字符串字面量共享同一个对象

    java
    String s1 = "hello";
    String s2 = "hello";
    System.out.println(s1 == s2); // true
    String s1 = "hello";
    String s2 = "hello";
    System.out.println(s1 == s2); // true
  • Integer 缓存:默认缓存 -128 到 127 的 Integer 对象

    java
    Integer i1 = 100;
    Integer i2 = 100;
    System.out.println(i1 == i2); // true
    
    Integer i3 = 200;
    Integer i4 = 200;
    System.out.println(i3 == i4); // false(超出缓存范围)
    Integer i1 = 100;
    Integer i2 = 100;
    System.out.println(i1 == i2); // true
    
    Integer i3 = 200;
    Integer i4 = 200;
    System.out.println(i3 == i4); // false(超出缓存范围)

四、行为型模式(Behavioral Patterns) ​

行为型模式关注对象之间的通信和职责分配。


4.1 策略模式(Strategy Pattern) ​

定义:定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。

java
// 策略接口
public interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略 A
public class AlipayStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("支付宝支付:" + amount + "元");
    }
}

// 具体策略 B
public class WechatPayStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("微信支付:" + amount + "元");
    }
}

// 具体策略 C
public class CreditCardStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("信用卡支付:" + amount + "元");
    }
}

// 上下文
public class PaymentContext {
    private PaymentStrategy strategy;

    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void executePayment(double amount) {
        strategy.pay(amount);
    }
}

// 使用
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100.0);
context.setStrategy(new WechatPayStrategy());
context.executePayment(200.0);
// 策略接口
public interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略 A
public class AlipayStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("支付宝支付:" + amount + "元");
    }
}

// 具体策略 B
public class WechatPayStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("微信支付:" + amount + "元");
    }
}

// 具体策略 C
public class CreditCardStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("信用卡支付:" + amount + "元");
    }
}

// 上下文
public class PaymentContext {
    private PaymentStrategy strategy;

    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void executePayment(double amount) {
        strategy.pay(amount);
    }
}

// 使用
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100.0);
context.setStrategy(new WechatPayStrategy());
context.executePayment(200.0);

Spring 中的策略模式注入:

java
// Spring 通过 @Autowired + Map 自动注入所有策略
@Component
public class PaymentService {
    @Autowired
    private Map<String, PaymentStrategy> strategyMap; // key=bean名称, value=策略实例

    public void pay(String channel, double amount) {
        PaymentStrategy strategy = strategyMap.get(channel + "PayStrategy");
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付渠道: " + channel);
        }
        strategy.pay(amount);
    }
}
// Spring 通过 @Autowired + Map 自动注入所有策略
@Component
public class PaymentService {
    @Autowired
    private Map<String, PaymentStrategy> strategyMap; // key=bean名称, value=策略实例

    public void pay(String channel, double amount) {
        PaymentStrategy strategy = strategyMap.get(channel + "PayStrategy");
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付渠道: " + channel);
        }
        strategy.pay(amount);
    }
}
  • 适用场景:系统有多种相似的算法,需要动态切换

4.2 模板方法模式(Template Method Pattern) ​

定义:定义一个操作中的算法骨架,将一些步骤延迟到子类中实现。

java
// 抽象类定义骨架
public abstract class AbstractCooking {
    // 模板方法(定义为 final,防止子类修改骨架)
    public final void cook() {
        prepareIngredients();
        heatOil();
        fry();
        addSeasoning();
        serve();
    }

    // 具体步骤(通用实现)
    private void heatOil() { System.out.println("热油"); }
    private void serve() { System.out.println("装盘上菜"); }

    // 抽象步骤(子类实现)
    protected abstract void prepareIngredients();
    protected abstract void fry();
    protected abstract void addSeasoning();

    // 钩子方法(可选覆盖)
    protected boolean needCutting() { return true; }
}

// 具体实现 A
public class TomatoEggCooking extends AbstractCooking {
    protected void prepareIngredients() {
        System.out.println("准备番茄和鸡蛋");
    }
    protected void fry() {
        System.out.println("先炒鸡蛋,再炒番茄");
    }
    protected void addSeasoning() {
        System.out.println("加盐和糖");
    }
}

// 具体实现 B
public class MapoTofuCooking extends AbstractCooking {
    protected void prepareIngredients() {
        System.out.println("准备豆腐和肉末");
    }
    protected void fry() {
        System.out.println("炒肉末,加豆瓣酱");
    }
    protected void addSeasoning() {
        System.out.println("加花椒粉和淀粉水");
    }
}
// 抽象类定义骨架
public abstract class AbstractCooking {
    // 模板方法(定义为 final,防止子类修改骨架)
    public final void cook() {
        prepareIngredients();
        heatOil();
        fry();
        addSeasoning();
        serve();
    }

    // 具体步骤(通用实现)
    private void heatOil() { System.out.println("热油"); }
    private void serve() { System.out.println("装盘上菜"); }

    // 抽象步骤(子类实现)
    protected abstract void prepareIngredients();
    protected abstract void fry();
    protected abstract void addSeasoning();

    // 钩子方法(可选覆盖)
    protected boolean needCutting() { return true; }
}

// 具体实现 A
public class TomatoEggCooking extends AbstractCooking {
    protected void prepareIngredients() {
        System.out.println("准备番茄和鸡蛋");
    }
    protected void fry() {
        System.out.println("先炒鸡蛋,再炒番茄");
    }
    protected void addSeasoning() {
        System.out.println("加盐和糖");
    }
}

// 具体实现 B
public class MapoTofuCooking extends AbstractCooking {
    protected void prepareIngredients() {
        System.out.println("准备豆腐和肉末");
    }
    protected void fry() {
        System.out.println("炒肉末,加豆瓣酱");
    }
    protected void addSeasoning() {
        System.out.println("加花椒粉和淀粉水");
    }
}

Spring 中的模板方法:

java
// JdbcTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<User> users = jdbcTemplate.query(
    "SELECT * FROM users",
    (rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);

// RestTemplate
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);
// JdbcTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<User> users = jdbcTemplate.query(
    "SELECT * FROM users",
    (rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);

// RestTemplate
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);

JdbcTemplate 内部使用模板方法模式:固定的流程(获取连接、创建语句、执行查询、处理结果集、关闭资源)由模板定义,其中的回调方法(如 RowMapper)由客户端实现。


4.3 观察者模式(Observer Pattern) ​

定义:定义对象间一种一对多的依赖关系,当一个对象状态发生变化时,所有依赖于它的对象都得到通知并自动更新。

发布-订阅模型是观察者模式的典型应用。

java
import java.util.ArrayList;
import java.util.List;

// 观察者接口
public interface Observer {
    void update(String message);
}

// 具体观察者
public class UserObserver implements Observer {
    private String name;

    public UserObserver(String name) { this.name = name; }

    public void update(String message) {
        System.out.println(name + " 收到消息: " + message);
    }
}

// 被观察者(主题)
public class Subject {
    private List<Observer> observers = new ArrayList<>();
    private String state;

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void detach(Observer observer) {
        observers.remove(observer);
    }

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

    private void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
}

// 使用
Subject subject = new Subject();
subject.attach(new UserObserver("张三"));
subject.attach(new UserObserver("李四"));
subject.setState("有新文章发布了!");
import java.util.ArrayList;
import java.util.List;

// 观察者接口
public interface Observer {
    void update(String message);
}

// 具体观察者
public class UserObserver implements Observer {
    private String name;

    public UserObserver(String name) { this.name = name; }

    public void update(String message) {
        System.out.println(name + " 收到消息: " + message);
    }
}

// 被观察者(主题)
public class Subject {
    private List<Observer> observers = new ArrayList<>();
    private String state;

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void detach(Observer observer) {
        observers.remove(observer);
    }

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

    private void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
}

// 使用
Subject subject = new Subject();
subject.attach(new UserObserver("张三"));
subject.attach(new UserObserver("李四"));
subject.setState("有新文章发布了!");

Spring 中的观察者模式:

java
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
    private Long orderId;
    public OrderCreatedEvent(Object source, Long orderId) {
        super(source);
        this.orderId = orderId;
    }
    public Long getOrderId() { return orderId; }
}

// 2. 发布事件
@Component
public class OrderService {
    @Autowired
    private ApplicationEventPublisher publisher;

    public void createOrder(Order order) {
        // 创建订单逻辑...
        publisher.publishEvent(new OrderCreatedEvent(this, order.getId()));
    }
}

// 3. 监听事件(方式一:实现接口)
@Component
public class EmailListener implements ApplicationListener<OrderCreatedEvent> {
    public void onApplicationEvent(OrderCreatedEvent event) {
        System.out.println("发送订单创建邮件,订单ID: " + event.getOrderId());
    }
}

// 4. 监听事件(方式二:注解,更常用)
@Component
public class SmsListener {
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        System.out.println("发送订单创建短信,订单ID: " + event.getOrderId());
    }
}

// 5. 异步监听(需要 @EnableAsync)
@Component
public class AsyncListener {
    @Async
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 异步处理,不影响主流程
        System.out.println("异步处理订单: " + event.getOrderId());
    }
}
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
    private Long orderId;
    public OrderCreatedEvent(Object source, Long orderId) {
        super(source);
        this.orderId = orderId;
    }
    public Long getOrderId() { return orderId; }
}

// 2. 发布事件
@Component
public class OrderService {
    @Autowired
    private ApplicationEventPublisher publisher;

    public void createOrder(Order order) {
        // 创建订单逻辑...
        publisher.publishEvent(new OrderCreatedEvent(this, order.getId()));
    }
}

// 3. 监听事件(方式一:实现接口)
@Component
public class EmailListener implements ApplicationListener<OrderCreatedEvent> {
    public void onApplicationEvent(OrderCreatedEvent event) {
        System.out.println("发送订单创建邮件,订单ID: " + event.getOrderId());
    }
}

// 4. 监听事件(方式二:注解,更常用)
@Component
public class SmsListener {
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        System.out.println("发送订单创建短信,订单ID: " + event.getOrderId());
    }
}

// 5. 异步监听(需要 @EnableAsync)
@Component
public class AsyncListener {
    @Async
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 异步处理,不影响主流程
        System.out.println("异步处理订单: " + event.getOrderId());
    }
}

4.4 责任链模式(Chain of Responsibility Pattern) ​

定义:使多个对象都有机会处理请求,将这些对象连成一条链,并沿着这条链传递请求直到有对象处理它。

java
// 抽象处理器
public abstract class Handler {
    protected Handler next;

    public void setNext(Handler next) {
        this.next = next;
    }

    public abstract void handleRequest(int level);
}

// 具体处理器 A
public class Level1Handler extends Handler {
    public void handleRequest(int level) {
        if (level <= 1) {
            System.out.println("Level1 处理了请求");
        } else if (next != null) {
            next.handleRequest(level);
        }
    }
}

// 具体处理器 B
public class Level2Handler extends Handler {
    public void handleRequest(int level) {
        if (level <= 2) {
            System.out.println("Level2 处理了请求");
        } else if (next != null) {
            next.handleRequest(level);
        }
    }
}

// 具体处理器 C
public class Level3Handler extends Handler {
    public void handleRequest(int level) {
        if (level <= 3) {
            System.out.println("Level3 处理了请求");
        } else {
            System.out.println("无人能处理该请求");
        }
    }
}

// 使用
Handler h1 = new Level1Handler();
Handler h2 = new Level2Handler();
Handler h3 = new Level3Handler();
h1.setNext(h2);
h2.setNext(h3);

h1.handleRequest(2); // Level2 处理了请求
// 抽象处理器
public abstract class Handler {
    protected Handler next;

    public void setNext(Handler next) {
        this.next = next;
    }

    public abstract void handleRequest(int level);
}

// 具体处理器 A
public class Level1Handler extends Handler {
    public void handleRequest(int level) {
        if (level <= 1) {
            System.out.println("Level1 处理了请求");
        } else if (next != null) {
            next.handleRequest(level);
        }
    }
}

// 具体处理器 B
public class Level2Handler extends Handler {
    public void handleRequest(int level) {
        if (level <= 2) {
            System.out.println("Level2 处理了请求");
        } else if (next != null) {
            next.handleRequest(level);
        }
    }
}

// 具体处理器 C
public class Level3Handler extends Handler {
    public void handleRequest(int level) {
        if (level <= 3) {
            System.out.println("Level3 处理了请求");
        } else {
            System.out.println("无人能处理该请求");
        }
    }
}

// 使用
Handler h1 = new Level1Handler();
Handler h2 = new Level2Handler();
Handler h3 = new Level3Handler();
h1.setNext(h2);
h2.setNext(h3);

h1.handleRequest(2); // Level2 处理了请求

实际应用:

框架责任链实现
Servlet FilterFilterChain 串联多个 Filter
Spring InterceptorHandlerExecutionChain 串联多个 HandlerInterceptor
Netty PipelineChannelPipeline 中的 ChannelHandler 链
Spring SecurityFilterChainProxy 管理安全过滤器链
MyBatis 插件InterceptorChain 拦截器链

Servlet Filter 示例:

java
@WebFilter("/*")
public class LogFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        System.out.println("日志过滤前");
        chain.doFilter(request, response); // 传递给下一个 Filter
        System.out.println("日志过滤后");
    }
}
@WebFilter("/*")
public class LogFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        System.out.println("日志过滤前");
        chain.doFilter(request, response); // 传递给下一个 Filter
        System.out.println("日志过滤后");
    }
}

4.5 命令模式(Command Pattern) ​

定义:将请求封装为一个对象,从而可以用不同的请求对客户进行参数化。

java
// 命令接口
public interface Command {
    void execute();
    void undo();
}

// 具体命令
public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) { this.light = light; }

    public void execute() { light.on(); }
    public void undo() { light.off(); }
}

public class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) { this.light = light; }

    public void execute() { light.off(); }
    public void undo() { light.on(); }
}

// 接收者
public class Light {
    public void on() { System.out.println("开灯"); }
    public void off() { System.out.println("关灯"); }
}

// 调用者
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }

    public void pressUndo() {
        command.undo();
    }
}
// 命令接口
public interface Command {
    void execute();
    void undo();
}

// 具体命令
public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) { this.light = light; }

    public void execute() { light.on(); }
    public void undo() { light.off(); }
}

public class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) { this.light = light; }

    public void execute() { light.off(); }
    public void undo() { light.on(); }
}

// 接收者
public class Light {
    public void on() { System.out.println("开灯"); }
    public void off() { System.out.println("关灯"); }
}

// 调用者
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }

    public void pressUndo() {
        command.undo();
    }
}

Java 中的命令模式:

java
// Runnable 接口就是一个命令
Thread thread = new Thread(() -> System.out.println("执行任务"));
thread.start();

// 线程池的任务队列
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> System.out.println("任务执行")); // 提交 Command
// Runnable 接口就是一个命令
Thread thread = new Thread(() -> System.out.println("执行任务"));
thread.start();

// 线程池的任务队列
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> System.out.println("任务执行")); // 提交 Command

4.6 状态模式(State Pattern) ​

定义:允许一个对象在其内部状态改变时改变它的行为。

java
// 状态接口
public interface State {
    void doAction(Context context);
}

// 具体状态 A
public class StartState implements State {
    public void doAction(Context context) {
        System.out.println("启动状态");
        context.setState(this);
    }
    public String toString() { return "Start"; }
}

// 具体状态 B
public class StopState implements State {
    public void doAction(Context context) {
        System.out.println("停止状态");
        context.setState(this);
    }
    public String toString() { return "Stop"; }
}

// 运行状态
public class RunningState implements State {
    public void doAction(Context context) {
        System.out.println("运行状态");
        context.setState(this);
    }
    public String toString() { return "Running"; }
}

// 上下文
public class Context {
    private State state;

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

    public State getState() {
        return state;
    }
}
// 状态接口
public interface State {
    void doAction(Context context);
}

// 具体状态 A
public class StartState implements State {
    public void doAction(Context context) {
        System.out.println("启动状态");
        context.setState(this);
    }
    public String toString() { return "Start"; }
}

// 具体状态 B
public class StopState implements State {
    public void doAction(Context context) {
        System.out.println("停止状态");
        context.setState(this);
    }
    public String toString() { return "Stop"; }
}

// 运行状态
public class RunningState implements State {
    public void doAction(Context context) {
        System.out.println("运行状态");
        context.setState(this);
    }
    public String toString() { return "Running"; }
}

// 上下文
public class Context {
    private State state;

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

    public State getState() {
        return state;
    }
}
  • 与策略模式的区别:状态模式中状态之间可以转换,策略模式中策略由客户端选择和切换
  • 适用场景:订单状态流转、流程审批等状态机场景

4.7 迭代器模式(Iterator Pattern) ​

定义:提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。

Java 集合框架中的迭代器模式:

java
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

// 迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

// 增强 for 循环本质就是使用迭代器
for (String s : list) {
    System.out.println(s);
}
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

// 迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

// 增强 for 循环本质就是使用迭代器
for (String s : list) {
    System.out.println(s);
}

自定义迭代器:

java
public interface MyIterator<E> {
    boolean hasNext();
    E next();
}

public class MyList<E> implements Iterable<E> {
    private E[] elements;
    private int size;

    public MyIterator<E> iterator() {
        return new MyIterator<E>() {
            private int index = 0;

            public boolean hasNext() {
                return index < size;
            }

            public E next() {
                return elements[index++];
            }
        };
    }
}
public interface MyIterator<E> {
    boolean hasNext();
    E next();
}

public class MyList<E> implements Iterable<E> {
    private E[] elements;
    private int size;

    public MyIterator<E> iterator() {
        return new MyIterator<E>() {
            private int index = 0;

            public boolean hasNext() {
                return index < size;
            }

            public E next() {
                return elements[index++];
            }
        };
    }
}

4.8 访问者模式(Visitor Pattern) ​

定义:表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素类的前提下定义作用于这些元素的新操作。

java
// 访问者接口
public interface Visitor {
    void visit(File file);
    void visit(Directory directory);
}

// 具体访问者:打印访问者
public class PrintVisitor implements Visitor {
    public void visit(File file) {
        System.out.println("文件: " + file.getName());
    }
    public void visit(Directory dir) {
        System.out.println("目录: " + dir.getName());
    }
}

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

// 具体元素 A
public class File implements Element {
    private String name;
    public File(String name) { this.name = name; }
    public String getName() { return name; }
    public void accept(Visitor visitor) { visitor.visit(this); }
}

// 具体元素 B
public class Directory implements Element {
    private String name;
    public Directory(String name) { this.name = name; }
    public String getName() { return name; }
    public void accept(Visitor visitor) { visitor.visit(this); }
}
// 访问者接口
public interface Visitor {
    void visit(File file);
    void visit(Directory directory);
}

// 具体访问者:打印访问者
public class PrintVisitor implements Visitor {
    public void visit(File file) {
        System.out.println("文件: " + file.getName());
    }
    public void visit(Directory dir) {
        System.out.println("目录: " + dir.getName());
    }
}

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

// 具体元素 A
public class File implements Element {
    private String name;
    public File(String name) { this.name = name; }
    public String getName() { return name; }
    public void accept(Visitor visitor) { visitor.visit(this); }
}

// 具体元素 B
public class Directory implements Element {
    private String name;
    public Directory(String name) { this.name = name; }
    public String getName() { return name; }
    public void accept(Visitor visitor) { visitor.visit(this); }
}

Java NIO FileVisitor:

java
Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("文件: " + file.getFileName());
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("目录: " + dir.getFileName());
        return FileVisitResult.CONTINUE;
    }
});
Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("文件: " + file.getFileName());
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("目录: " + dir.getFileName());
        return FileVisitResult.CONTINUE;
    }
});

4.9 中介者模式(Mediator Pattern) ​

定义:用一个中介对象来封装一系列对象的交互,使各对象不需要显式地相互引用。

java
// 中介者接口
public interface Mediator {
    void send(String message, Colleague colleague);
}

// 具体中介者
public class ChatRoom implements Mediator {
    public void send(String message, Colleague colleague) {
        System.out.println(colleague.getName() + " 发送消息: " + message);
    }
}

// 同事类
public abstract class Colleague {
    protected Mediator mediator;
    protected String name;

    public Colleague(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public String getName() { return name; }
    public abstract void send(String message);
    public abstract void receive(String message);
}

// 具体同事
public class User extends Colleague {
    public User(Mediator mediator, String name) {
        super(mediator, name);
    }

    public void send(String message) {
        mediator.send(message, this);
    }

    public void receive(String message) {
        System.out.println(name + " 收到: " + message);
    }
}
// 中介者接口
public interface Mediator {
    void send(String message, Colleague colleague);
}

// 具体中介者
public class ChatRoom implements Mediator {
    public void send(String message, Colleague colleague) {
        System.out.println(colleague.getName() + " 发送消息: " + message);
    }
}

// 同事类
public abstract class Colleague {
    protected Mediator mediator;
    protected String name;

    public Colleague(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public String getName() { return name; }
    public abstract void send(String message);
    public abstract void receive(String message);
}

// 具体同事
public class User extends Colleague {
    public User(Mediator mediator, String name) {
        super(mediator, name);
    }

    public void send(String message) {
        mediator.send(message, this);
    }

    public void receive(String message) {
        System.out.println(name + " 收到: " + message);
    }
}

MVC 中的中介者:Controller 充当 View 和 Model 之间的中介者,协调视图和数据模型的交互。


4.10 备忘录模式(Memento Pattern) ​

定义:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复。

java
// 备忘录
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;
        System.out.println("设置状态: " + state);
    }

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

    public void restoreStateFromMemento(Memento memento) {
        state = memento.getState();
        System.out.println("恢复状态: " + state);
    }
}

// 管理者
public class CareTaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}
// 备忘录
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;
        System.out.println("设置状态: " + state);
    }

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

    public void restoreStateFromMemento(Memento memento) {
        state = memento.getState();
        System.out.println("恢复状态: " + state);
    }
}

// 管理者
public class CareTaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}

Java 中的备忘录模式:对象序列化(Serializable)是备忘录模式的一种体现,将对象状态保存到字节流中,可以随时恢复。


4.11 解释器模式(Interpreter Pattern) ​

定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器来解释语言中的句子。

java
// 抽象表达式
public interface Expression {
    int interpret();
}

// 终结符表达式:数字
public class NumberExpression implements Expression {
    private int number;
    public NumberExpression(int number) { this.number = number; }
    public int interpret() { return number; }
}

// 非终结符表达式:加法
public class AddExpression implements Expression {
    private Expression left, right;
    public AddExpression(Expression left, Expression right) {
        this.left = left; this.right = right;
    }
    public int interpret() { return left.interpret() + right.interpret(); }
}

// 非终结符表达式:减法
public class SubtractExpression implements Expression {
    private Expression left, right;
    public SubtractExpression(Expression left, Expression right) {
        this.left = left; this.right = right;
    }
    public int interpret() { return left.interpret() - right.interpret(); }
}

// 使用
// 表达式: 10 + 20 - 5
Expression result = new SubtractExpression(
    new AddExpression(new NumberExpression(10), new NumberExpression(20)),
    new NumberExpression(5)
);
System.out.println(result.interpret()); // 25
// 抽象表达式
public interface Expression {
    int interpret();
}

// 终结符表达式:数字
public class NumberExpression implements Expression {
    private int number;
    public NumberExpression(int number) { this.number = number; }
    public int interpret() { return number; }
}

// 非终结符表达式:加法
public class AddExpression implements Expression {
    private Expression left, right;
    public AddExpression(Expression left, Expression right) {
        this.left = left; this.right = right;
    }
    public int interpret() { return left.interpret() + right.interpret(); }
}

// 非终结符表达式:减法
public class SubtractExpression implements Expression {
    private Expression left, right;
    public SubtractExpression(Expression left, Expression right) {
        this.left = left; this.right = right;
    }
    public int interpret() { return left.interpret() - right.interpret(); }
}

// 使用
// 表达式: 10 + 20 - 5
Expression result = new SubtractExpression(
    new AddExpression(new NumberExpression(10), new NumberExpression(20)),
    new NumberExpression(5)
);
System.out.println(result.interpret()); // 25
  • 适用场景:正则表达式解析、SQL 解析、模板引擎
  • 使用频率:较低,在特定领域(DSL、表达式解析)中使用

五、设计模式在 Spring 中的应用汇总 ​

Spring 框架充分运用了各种设计模式,下表总结了主要的应用场景:

设计模式Spring 中的应用
工厂模式BeanFactory、ApplicationContext、FactoryBean
单例模式Bean 的默认作用域 singleton,容器级单例
代理模式AOP 底层实现(JDK 动态代理 / CGLIB 代理)
模板方法模式JdbcTemplate、RestTemplate、JmsTemplate、TransactionTemplate
观察者模式ApplicationListener、@EventListener、ApplicationEventPublisher
责任链模式HandlerInterceptor 拦截器链、Filter 过滤器链
适配器模式HandlerAdapter(适配不同 Controller 类型)、AdvisorAdapter
策略模式Resource 接口的不同实现、AuthenticationProvider
装饰器模式HttpServletRequestWrapper、HttpServletResponseWrapper、TransactionAwareCacheDecorator
外观模式JdbcUtils、TransactionSynchronizationManager
建造者模式UriComponentsBuilder、MockMvcBuilders、SecurityFilterChainBuilder
原型模式Bean 作用域 prototype 每次获取都创建新实例
桥接模式ViewResolver 的抽象与实现分离
命令模式PlatformTransactionManager(将事务操作封装为命令)
迭代器模式CompositeIterator 遍历组合对象
中介者模式Controller 作为 View 和 Model 的中介者(MVC)
享元模式连接池、Bean 缓存中复用对象

IoC 容器中的工厂 + 单例 ​

java
// IoC 容器本质:工厂模式 + 单例模式
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 工厂模式:getBean 创建或获取对象
UserService userService = context.getBean(UserService.class);

// 单例模式:默认每个 Bean 在一个容器中只有一个实例
UserService s1 = context.getBean(UserService.class);
UserService s2 = context.getBean(UserService.class);
System.out.println(s1 == s2); // true
// IoC 容器本质:工厂模式 + 单例模式
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 工厂模式:getBean 创建或获取对象
UserService userService = context.getBean(UserService.class);

// 单例模式:默认每个 Bean 在一个容器中只有一个实例
UserService s1 = context.getBean(UserService.class);
UserService s2 = context.getBean(UserService.class);
System.out.println(s1 == s2); // true

AOP 中的代理模式 ​

java
@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("方法执行前: " + joinPoint.getSignature());
        Object result = joinPoint.proceed();
        System.out.println("方法执行后: " + joinPoint.getSignature());
        return result;
    }
}
@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("方法执行前: " + joinPoint.getSignature());
        Object result = joinPoint.proceed();
        System.out.println("方法执行后: " + joinPoint.getSignature());
        return result;
    }
}

Spring AOP 在运行时为目标对象创建代理对象,在调用目标方法时插入切面逻辑。

Template 中的模板方法模式 ​

java
// JdbcTemplate 固定了数据库操作的骨架
jdbcTemplate.execute("CREATE TABLE users (id INT, name VARCHAR(20))");

// 只需要提供 SQL 语句和处理结果的回调
List<User> users = jdbcTemplate.query(
    "SELECT * FROM users WHERE age > ?",
    new Object[]{18},
    (rs, rowNum) -> new User(rs.getInt("id"), rs.getString("name"))
);
// JdbcTemplate 固定了数据库操作的骨架
jdbcTemplate.execute("CREATE TABLE users (id INT, name VARCHAR(20))");

// 只需要提供 SQL 语句和处理结果的回调
List<User> users = jdbcTemplate.query(
    "SELECT * FROM users WHERE age > ?",
    new Object[]{18},
    (rs, rowNum) -> new User(rs.getInt("id"), rs.getString("name"))
);

Listener 中的观察者模式 ​

java
// Spring 事件驱动机制是观察者模式的进阶实现
// 支持同步/异步、泛型事件、条件监听(@EventListener(condition = "..."))
// 事务绑定事件(@TransactionalEventListener)
// Spring 事件驱动机制是观察者模式的进阶实现
// 支持同步/异步、泛型事件、条件监听(@EventListener(condition = "..."))
// 事务绑定事件(@TransactionalEventListener)

Filter 中的责任链模式 ​

java
// Spring Security 基于责任链模式构建安全过滤链
// 每个过滤器负责一项安全检查:认证、授权、CSRF、CORS 等
// 请求在过滤链中依次通过各过滤器

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults())
            .csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }
}
// Spring Security 基于责任链模式构建安全过滤链
// 每个过滤器负责一项安全检查:认证、授权、CSRF、CORS 等
// 请求在过滤链中依次通过各过滤器

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults())
            .csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }
}

Adapter 中的适配器模式 ​

java
// Spring MVC 通过 HandlerAdapter 适配不同类型的处理器
// - SimpleControllerHandlerAdapter:适配 Controller 接口
// - HttpRequestHandlerAdapter:适配 HttpRequestHandler
// - AnnotationMethodHandlerAdapter:适配 @RequestMapping 方法(最常用)
// - SimpleServletHandlerAdapter:适配 Servlet

@RestController
public class UserController {
    @GetMapping("/users")
    public List<User> listUsers() {
        // 处理器方法的参数和返回值由 HandlerAdapter 适配
        return userService.findAll();
    }
}
// Spring MVC 通过 HandlerAdapter 适配不同类型的处理器
// - SimpleControllerHandlerAdapter:适配 Controller 接口
// - HttpRequestHandlerAdapter:适配 HttpRequestHandler
// - AnnotationMethodHandlerAdapter:适配 @RequestMapping 方法(最常用)
// - SimpleServletHandlerAdapter:适配 Servlet

@RestController
public class UserController {
    @GetMapping("/users")
    public List<User> listUsers() {
        // 处理器方法的参数和返回值由 HandlerAdapter 适配
        return userService.findAll();
    }
}

六、总结 ​

6.1 设计模式选择指南 ​

需求场景推荐模式
需要全局唯一实例单例模式
需要灵活创建对象工厂方法 / 抽象工厂
对象构建过程复杂建造者模式
需要大量相似对象原型模式(克隆)
需要控制对象访问代理模式
接口不兼容需要转换适配器模式
需要动态添加功能装饰器模式
简化复杂子系统访问外观模式
处理树形层次结构组合模式
抽象与实现需要独立变化桥接模式
共享大量细粒度对象享元模式
算法需要动态切换策略模式
算法骨架固定、步骤可变模板方法模式
一对多依赖通知观察者模式
请求需要多级处理责任链模式
请求需要排队/撤销命令模式
对象行为依赖其状态状态模式
需统一遍历集合元素迭代器模式
需在不改元素类的前提下增加操作访问者模式
多对象交互需解耦中介者模式
需要保存和恢复对象状态备忘录模式
需要解释自定义语言解释器模式

6.2 核心要点 ​

  • 设计原则优先于设计模式:不要为了用模式而用模式,遵循 SOLID 原则往往比套用模式更重要
  • 组合优于继承:大多数设计模式都强调使用组合而非继承来复用代码
  • 面向接口编程:将抽象与实现分离,降低耦合
  • 开闭原则是核心:对扩展开放、对修改关闭是所有设计模式的共同追求
  • 模式是工具不是教条:根据实际场景灵活应用,可以变体、组合使用多种模式

6.3 常见面试题 ​

  1. 单例模式的几种写法及优缺点?如何防止反射和序列化破坏?
  2. JDK 动态代理与 CGLIB 动态代理的区别?Spring AOP 如何选择?
  3. 简单工厂、工厂方法、抽象工厂的区别与联系?
  4. 策略模式与状态模式的区别?
  5. 装饰器模式与代理模式的区别?(装饰器侧重功能增强,代理侧重访问控制)
  6. 适配器模式与装饰器模式的区别?(适配器用于接口转换,装饰器用于功能扩展)
  7. Spring 中用到了哪些设计模式?请举例说明。
  8. 如何实现一个线程安全的懒加载单例?(DCL + volatile,或静态内部类,或枚举)
  9. 模板方法模式与策略模式的区别?(模板方法强调算法骨架固定,策略强调算法可替换)
  10. 观察者模式中推模型与拉模型的区别?