#设计模式在框架源码中的应用
#一个面试问题的本质
面试官问:"你在项目中用过哪些设计模式?"
大多数候选人会回答:"工厂模式、单例模式、策略模式..."
面试官追问:"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
StringBuilder 的 append 方法链式调用,本质上是建造者模式的变体:
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 高频源码设计模式清单
| 模式 | JDK | Spring | MyBatis |
|---|---|---|---|
| 单例 | Runtime | 无(IOC 容器管理) | SqlSessionFactory |
| 工厂 | Calendar | BeanFactory | SqlSessionFactoryBuilder |
| 建造者 | StringBuilder | Environment | SqlSessionFactoryBuilder |
| 模板方法 | AQS | BeanPostProcessor | BaseExecutor |
| 策略 | ThreadPoolExecutor | Resource | - |
| 代理 | - | JdkDynamicAopProxy | MapperProxy |
| 装饰器 | I/O 流 | WebSocketDecorator | - |
| 适配器 | Collections.enumeration | HandlerAdapter | - |
| 观察者 | PropertyChangeSupport | ApplicationListener | - |
| 责任链 | - | HandlerInterceptor | - |
#7.2 级别差异
| 级别 | 期望回答 |
|---|---|
| P5 | 能识别常见设计模式的写法 |
| P6 | 能从 JDK/Spring 源码中找出设计模式 |
| P7 | 能分析为什么框架选择这个模式而不是另一个,理解设计权衡 |