设计模式在框架源码中的应用

一个面试问题的本质

面试官问:"你在项目中用过哪些设计模式?"

大多数候选人会回答:"工厂模式、单例模式、策略模式..."

面试官追问:"JDK 源码里有哪些设计模式?Spring 框架呢?"

能回答出来的不到 20%。

会用手写设计模式是 60 分,能从源码中识别设计模式、理解为什么这么用,是 80 分以上的能力。


一、创建型模式在源码中的应用🟡

1.1 单例模式:Runtime

JDK 的 Runtime 类是单例模式的经典应用:

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    private Runtime() {} // 私有构造函数

    // 实例方法
    public void addShutdownHook(Thread hook) { ... }
    public Process exec(String command) { ... }
}

1.2 工厂模式:Calender

Calendar.getInstance() 就是一个工厂方法:

public abstract class Calendar {
    public static Calendar getInstance() {
        return createCalendar(TimeZone.getDefaultRef(), Locale.getDefault());
    }

    private static Calendar createCalendar(TimeZone zone, Locale aLocale) {
        // 根据系统配置创建不同子类的实例
        CalendarProvider provider =
            AccessController.doPrivileged(new CalendarSystemPropertyProvider());

        Calendar cal = provider.getInstance(zone, aLocale);

        // 替换逻辑...
        if (cal.getClass().equals(GregorianCalendar.class)) {
            // Windows 系统用不同的实例
        }
        return cal;
    }
}

1.3 建造者模式:StringBuilder

StringBuilderappend 方法链式调用,本质上是建造者模式的变体:

String result = new StringBuilder()
    .append("Hello")
    .append(" ")
    .append("World")
    .toString();

1.4 原型模式:ArrayList.clone()

public class ArrayList<E> {
    public Object clone() {
        try {
            ArrayList<?> result = (ArrayList<?>) super.clone();
            result.elementData = Arrays.copyOf(this.elementData, this.size);
            return result;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
}

ArrayList.clone() 是浅拷贝,JDK 源码直接写在这里,没有特殊处理深拷贝。


二、结构型模式在源码中的应用🟡

2.1 装饰器模式:Java I/O 流

前面详细讲过,Java I/O 库是装饰器模式的教科书式实现。

2.2 代理模式:JDBC

JDBC 的 DataSource 就是一个代理:

public interface DataSource extends CommonDataSource, Wrapper {
    Connection getConnection() throws SQLException;
}

// 你获取的 Connection 实际上是被 DriverManager 代理的对象
Connection conn = dataSource.getConnection();
// 真正的连接可能是:
// 1. 真实数据库连接
// 2. 数据库连接池的代理(复用连接)
// 3. 分布式数据库的代理(路由)
// 4. 读写分离的代理(自动路由)

2.3 适配器模式:Collections

Collections 类的 enumeration() 方法是适配器模式:

public static <T> Enumeration<T> enumeration(final Collection<T> c) {
    return new Enumeration<T>() {
        Iterator<T> i = c.iterator();

        public boolean hasMoreElements() {
            return i.hasNext();
        }

        public T nextElement() {
            return i.next();
        }
    };
}

Iterator 适配成 Enumeration(JDK 1.0 的遗留接口)。

2.4 门面模式:JDBC Transaction

JDBC 的 API 本身就是门面模式:

// 客户端不需要知道底层细节
Connection conn = DriverManager.getConnection(url, user, pwd);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);

// JDBC 封装了:
// 1. 网络通信(与数据库通信)
// 2. 协议解析(SQL 语句解析)
// 3. 数据转换(ResultSet → Java 对象)

三、行为型模式在源码中的应用🔴

3.1 模板方法:AQS

AbstractQueuedSynchronizer 是 JDK 并发包的基石,它的核心就是模板方法:

public abstract class AbstractQueuedSynchronizer {
    // 模板方法:获取锁
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&           // 钩子方法:子类实现
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
            selfInterrupt();
        }
    }

    // 钩子方法:尝试获取锁
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    // 钩子方法:尝试释放锁
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    // 钩子方法:是否需要阻塞
    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }
}

ReentrantLock 就是通过继承 AQS 并实现这些钩子方法:

public class ReentrantLock implements Lock {
    private final Sync sync;

    abstract static class Sync extends AbstractQueuedSynchronizer {
        abstract void lock();
    }

    static final class NonfairSync extends Sync {
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    static final class FairSync extends Sync {
        protected final boolean tryAcquire(int acquires) {
            return fairTryAcquire(acquires);
        }
    }
}

3.2 策略模式:ThreadPoolExecutor

线程池的拒绝策略就是策略模式:

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

// 四种内置策略
class AbortPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r + " rejected");
    }
}

class CallerRunsPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run(); // 由调用线程执行
        }
    }
}

class DiscardPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // 直接丢弃
    }
}

class DiscardOldestPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll(); // 丢弃队列中最老的
            e.execute(r);
        }
    }
}

3.3 观察者模式:JDK PropertyChangeSupport

public class PropertyChangeSupport {
    private List<PropertyChangeListener> listeners = new ArrayList<>();

    public void addPropertyChangeListener(PropertyChangeListener l) {
        listeners.add(l);
    }

    public void firePropertyChange(String name, Object oldVal, Object newVal) {
        for (PropertyChangeListener l : listeners) {
            l.propertyChange(new PropertyChangeEvent(this, name, oldVal, newVal));
        }
    }
}

// 使用
class User {
    private final PropertyChangeSupport support = new PropertyChangeSupport(this);
    private String name;

    public void setName(String name) {
        String old = this.name;
        this.name = name;
        support.firePropertyChange("name", old, name);
    }
}

3.4 责任链模式:Tomcat Valve

Tomcat 的 Valve 是责任链模式的实现:

public interface Valve {
    Valve getNext();
    void setNext(Valve valve);
    void invoke(Request request, Response response);
}

// Tomcat 的认证 Valve
public class AuthenticatorBase extends Valve {
    @Override
    public void invoke(Request request, Response response) {
        if (request.getAuthType() == null) {
            login(request, response);
            // 不调用下一个 Valve,等待登录成功
        } else {
            getNext().invoke(request, response); // 传递
        }
    }
}

// 日志 Valve
public class AccessLogValve extends ValveBase {
    @Override
    public void invoke(Request request, Response response) {
        long start = System.nanoTime();
        getNext().invoke(request, response); // 先传递给下一个
        log(request, response, start);       // 后处理日志
    }
}

四、Spring 框架中的设计模式🟡

4.1 Spring BeanFactory:工厂模式

Spring 的 BeanFactory 是工厂模式的集大成者:

public interface BeanFactory {
    Object getBean(String name);
    <T> T getBean(Class<T> requiredType);
    <T> T getBean(String name, Object... args);
}

// DefaultListableBeanFactory:Spring 的核心工厂实现
public class DefaultListableBeanFactory
        extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
}

4.2 Spring BeanPostProcessor:模板方法 + 策略

Bean 的初始化过程用了模板方法:

public interface BeanPostProcessor {
    // 钩子方法
    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

// Spring 的 AOP 自动代理创建器
class AbstractAutoProxyCreator implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 如果这个 bean 需要代理,就返回代理对象
        return wrapIfNecessary(bean, beanName);
    }
}

// Spring 的 @Autowired 注解处理
class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessProperties(...) {
        // 注入 @Autowired 标注的依赖
        injectionMetadata.inject(bean, beanName);
        return bean;
    }
}

4.3 Spring Resource:策略模式

Resource 接口是策略模式的体现:

public interface Resource {
    InputStream getInputStream() throws IOException;
}

// 不同策略
class ClassPathResource implements Resource {
    @Override
    public InputStream getInputStream() {
        return classLoader.getResourceAsStream(path);
    }
}

class FileSystemResource implements Resource {
    @Override
    public InputStream getInputStream() {
        return new FileInputStream(file);
    }
}

class UrlResource implements Resource {
    @Override
    public InputStream getInputStream() {
        return url.openStream();
    }
}

// 使用
Resource resource = new ClassPathResource("config.xml");
// 替换实现只需要改这一行

4.4 Spring FactoryBean:工厂 + 代理

public interface FactoryBean<T> {
    T getObject(); // 创建的对象
    Class<?> getObjectType(); // 对象类型
    boolean isSingleton();
}

// MyBatis 的 SqlSessionFactoryBean
class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory> {
    @Override
    public SqlSessionFactory getObject() {
        return buildSqlSessionFactory();
    }

    @Override
    public Class<?> getObjectType() {
        return SqlSessionFactory.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

// Spring 容器中的使用
SqlSessionFactory factory = applicationContext.getBean(SqlSessionFactory.class);
// 实际返回的是 SqlSessionFactoryBean.getObject() 的结果

4.5 Spring MVC HandlerMapping:策略模式

public interface HandlerMapping {
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

// URL 对应的 Controller
class RequestMappingHandlerMapping implements HandlerMapping {
    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) {
        String url = request.getRequestURI();
        Controller controller = mapping.get(url); // O(1) 查找
        return new HandlerExecutionChain(controller);
    }
}

// Controller 名字对应的 Controller
class BeanNameUrlHandlerMapping implements HandlerMapping {
    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) {
        // /user/* → UserController
    }
}

五、MyBatis 中的设计模式🟡

5.1 代理模式:Mapper 代理

MyBatis 不让你直接写 DAO 实现,而是生成代理:

// 你写的接口
interface UserMapper {
    User selectById(Long id);
}

// MyBatis 动态生成的代理
class MapperProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            MappedStatement ms = configuration.getMappedStatement(method);
            return session.selectOne(ms, args);
        } finally {
            session.close();
        }
    }
}

// 使用
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectById(1L); // 实际是调用了 MapperProxy.invoke()

5.2 建造者模式:SqlSessionFactoryBuilder

// SqlSessionFactoryBuilder:建造者
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
    .build(inputStream); // 使用默认配置

SqlSessionFactory factory2 = new SqlSessionFactoryBuilder()
    .build(inputStream, environment, properties); // 自定义配置

// 内部实现
public SqlSessionFactory build(InputStream inputStream, String environment, Properties props) {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, props);
    return build(parser.parse()); // 逐步构建
}

六、生产选型指南

6.1 设计模式选择决策树

需要创建对象吗?
├── 复杂对象,参数多 → 建造者模式
├── 创建成本高,可复制 → 原型模式
├── 需要工厂统一管理 → 工厂模式
└── 需要单例 → 枚举单例

需要扩展对象行为吗?
├── 运行时动态添加 → 装饰器模式
├── 需要代理控制访问 → 代理模式
└── 需要透明包装 → 外观模式

需要组织对象关系吗?
├── 有继承关系 → 组合模式
├── 需要树形结构 → 组合模式
└── 对象需要相互通信 → 观察者模式

需要控制行为流程吗?
├── 流程固定,部分可变 → 模板方法模式
├── 行为独立,可替换 → 策略模式
├── 有多个处理器 → 责任链模式
└── 状态决定行为 → 状态模式

需要接口转换吗?
├── 接口不兼容 → 适配器模式
└── 接口需要简化 → 门面模式

【面试官心理】 能说出源码中的设计模式只是第一步。更重要的是理解为什么框架作者选择这个模式而不是另一个。比如 Spring 为什么用 BeanFactory + FactoryBean 而不是简单的工厂模式?这背后的权衡才是 P7 级别需要展示的能力。


七、面试总结

7.1 高频源码设计模式清单

模式JDKSpringMyBatis
单例Runtime无(IOC 容器管理)SqlSessionFactory
工厂CalendarBeanFactorySqlSessionFactoryBuilder
建造者StringBuilderEnvironmentSqlSessionFactoryBuilder
模板方法AQSBeanPostProcessorBaseExecutor
策略ThreadPoolExecutorResource-
代理-JdkDynamicAopProxyMapperProxy
装饰器I/O 流WebSocketDecorator-
适配器Collections.enumerationHandlerAdapter-
观察者PropertyChangeSupportApplicationListener-
责任链-HandlerInterceptor-

7.2 级别差异

级别期望回答
P5能识别常见设计模式的写法
P6能从 JDK/Spring 源码中找出设计模式
P7能分析为什么框架选择这个模式而不是另一个,理解设计权衡