设计模式面试复习笔记
在准备后端面试时,设计模式几乎是绕不开的话题。
很多框架(例如 Spring)内部大量使用了设计模式,因此理解这些模式不仅有助于写业务代码,也能更好地理解框架源码。
设计模式本质上是:
针对常见软件设计问题的通用解决方案。
经典设计模式共有 23 种,通常分为三大类:
| 类型 | 作用 |
|---|---|
| 创建型模式 | 解决对象创建问题 |
| 结构型模式 | 解决类或对象组合问题 |
| 行为型模式 | 解决对象之间交互问题 |
面试中最常问的其实只有几种,下面整理几个高频模式。
一、单例模式(Singleton)
1. 解决的问题
确保某个类在系统中只有一个实例,并提供全局访问方式。
典型场景:
- 配置管理
- 日志对象
- 数据库连接池
- Spring Bean 默认单例
2. 基本实现(线程不安全)
1 | public class Singleton { |
这个版本在多线程环境下不安全。
3. 面试常问:线程安全实现(DCL)
1 | public class Singleton { |
关键点:
volatile防止指令重排- 双重检查减少锁开销
4. 更简单写法(推荐)
1 | public class Singleton { |
利用类加载机制保证线程安全,写法也更简洁。
二、工厂模式(Factory)
1. 解决的问题
当对象创建逻辑复杂时,将对象创建过程封装起来。
核心思想:
让对象的创建和使用分离。
2. 简单工厂示例
假设系统支持多种消息发送方式:邮件、短信、推送。
统一接口:
1 | public interface MessageSender { |
实现类:
1 | public class EmailSender implements MessageSender { |
工厂类:
1 | public class MessageFactory { |
使用方式:
1 | MessageSender sender = MessageFactory.create("email"); |
3. 面试常问
简单工厂 vs 工厂方法:
| 模式 | 特点 |
|---|---|
| 简单工厂 | 一个工厂类创建所有对象 |
| 工厂方法 | 每种产品对应一个工厂 |
工厂方法接口示例:
1 | public interface Factory { |
三、策略模式(Strategy)
1. 解决的问题
当一个功能有多种实现方式时,可以在运行时动态选择算法。
核心思想:
将不同算法封装为独立策略。
2. 示例:支付系统
支付策略接口:
1 | public interface PayStrategy { |
支付宝策略:
1 | public class AlipayStrategy implements PayStrategy { |
微信策略:
1 | public class WechatPayStrategy implements PayStrategy { |
使用方式:
1 | PayStrategy strategy = new AlipayStrategy(); |
3. 面试延伸
Spring 中大量使用策略模式,例如:
HandlerMappingHandlerAdapterViewResolver
通过接口定义统一行为,不同实现类提供不同策略。
四、观察者模式(Observer)
1. 解决的问题
当一个对象状态变化时,自动通知其他对象。
核心思想:
发布-订阅机制。
2. 示例
观察者接口:
1 | public interface Observer { |
具体观察者:
1 | public class UserObserver implements Observer { |
被观察对象:
1 | import java.util.ArrayList; |
3. 实际应用
典型场景:
- Spring 事件机制
- 消息订阅
- GUI 事件监听
- MQ 消费者模型
五、代理模式(Proxy)
1. 解决的问题
为对象提供一个代理对象,控制对原对象的访问。
常见用途:
- 权限控制
- 日志记录
- 延迟加载
- AOP
2. 示例
接口:
1 | public interface Service { |
真实对象:
1 | public class RealService implements Service { |
代理对象:
1 | public class ServiceProxy implements Service { |
3. 面试重点
Spring AOP 本质就是代理模式:
- JDK 动态代理
- CGLIB 动态代理
六、面试中常见问题
1. Spring 用到了哪些设计模式?
常见答案:
- 单例模式(Bean 默认单例)
- 工厂模式(
BeanFactory) - 策略模式(
HandlerMapping) - 代理模式(AOP)
- 模板方法模式(
JdbcTemplate) - 观察者模式(Spring Event)
2. 单例模式为什么需要 volatile?
因为 JVM 可能发生指令重排。
对象创建步骤本应是:
- 分配内存
- 初始化对象
- 指向对象
但可能重排为:
- 分配内存
- 指向对象
- 初始化对象
这样会导致其他线程拿到“未初始化完成”的对象。
volatile 可以禁止这类重排。
3. 策略模式和工厂模式区别
| 模式 | 关注点 |
|---|---|
| 工厂模式 | 对象创建 |
| 策略模式 | 算法选择 |
很多时候这两个模式会结合使用:先由工厂创建策略对象,再在运行时切换策略。
总结
面试中复习设计模式,不需要死记 23 种模式的所有细节。
更重要的是把握这三点:
- 这个模式解决了什么问题
- 在项目中哪里能用
- 在 Spring 或常见框架中有什么对应落地
如果你能结合业务场景讲清楚“为什么用、怎么用、有哪些权衡”,通常会比只背定义更有说服力。
