什么是设计模式?它能带来哪些好处?
面试考察点
-
概念理解:面试官不仅仅是想知道你背没背定义,更是想知道你是否理解设计模式的本质——它是解决特定场景下软件设计问题的通用方案,而不是死板的教条。
-
实践经验:考察你在实际项目中是否用过设计模式,能不能结合真实场景说出 "我用了 XX 模式解决了 XX问题",而不是纸上谈兵。
-
设计思维:能否从更高的维度理解设计模式背后的设计原则(SOLID 等),说明你具备良好的架构思维。
核心答案
设计模式(Design Pattern)是在软件开发中,针对反复出现的设计问题所总结出的通用解决方案。它不是可以直接复制的代码,而是一种解决特定问题的思路模板。
这个概念最早由 "四人帮"(GoF,Gang of Four)在 1994 年的著作《设计模式:可复用面向对象软件的基础》中系统提出,总结了 23 种经典设计模式。
设计模式能带来的核心好处:
| 好处 | 说明 |
|---|---|
| 提高代码复用性 | 成熟方案可直接套用,避免重复造轮子 |
| 增强可维护性 | 结构清晰的代码更易理解和修改 |
| 提升扩展性 | 遵循 "对扩展开放,对修改关闭" 的原则 |
| 降低沟通成本 | 团队用统一术语交流,"这里用策略模式" 一听就懂 |
| 减少设计缺陷 | 经过大量实践验证,避免踩前人踩过的坑 |
深度解析
一、23 种设计模式速览
GoF 的 23 种设计模式按用途分为三大类:
上图展示了 GoF 23 种设计模式的完整分类,面试时不用全部背下来,但至少要记住 三大类的划分逻辑:
- 创建型:关注对象的创建机制,把对象的创建和使用解耦。比如你不会
new一个具体的实现类,而是通过工厂来获取。 - 结构型:关注类和对象的组合方式,像搭积木一样把不同的组件拼装在一起。比如适配器模式让不兼容的接口能协同工作。
- 行为型:关注对象之间的通信和职责分配,定义 "谁做什么、怎么做"。比如策略模式让算法可以独立变化。
二、设计模式的底层基石——七大设计原则
设计模式不是凭空想出来的,它们都遵循一些基本的设计原则,合称 SOLID 原则(加上迪米特法则和合成复用原则共 7 个):
| 原则 | 核心思想 | 一句话理解 |
|---|---|---|
| 单一职责原则 (SRP) | 一个类只做一件事 | 别把所有功能塞一个类里 |
| 开闭原则 (OCP) | 对扩展开放,对修改关闭 | 加功能不改老代码 |
| 里氏替换原则 (LSP) | 子类可以替换父类 | 继承要靠谱,别搞特殊 |
| 接口隔离原则 (ISP) | 接口要小而专 | 别搞一个万能大接口 |
| 依赖倒置原则 (DIP) | 依赖抽象而非实现 | 面向接口编程 |
| 迪米特法则 (LoD) | 最少知道原则 | 别打听不需要知道的事 |
| 合成复用原则 (CRP) | 优先组合而非继承 | 能组合就别继承 |
举个实际的例子——策略模式背后的设计原则:
// 没用策略模式:违反开闭原则,每次加支付方式都要改代码
public class PaymentService {
public void pay(String type, BigDecimal amount) {
if ("alipay".equals(type)) {
// 支付宝支付逻辑...
} else if ("wechat".equals(type)) {
// 微信支付逻辑...
}
// 每加一种支付方式,这里就要改一次 💣
}
}
// 用了策略模式:符合开闭原则,新支付方式只需新增一个类
public interface PaymentStrategy {
void pay(BigDecimal amount);
}
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
// 支付宝支付逻辑
}
}
public class WechatPayStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
// 微信支付逻辑
}
}
// 新加支付方式?写个新类就行,老代码一行不动 ✅
三、实际项目中设计模式的应用
这块面试官特别爱追问。我挑几个最常用的说说:
| 设计模式 | 典型应用场景 | 框架中的体现 |
|---|---|---|
| 单例模式 | 数据库连接池、配置管理 | Spring Bean 默认单例 |
| 工厂模式 | 根据类型创建不同对象 | Spring 的 BeanFactory |
| 策略模式 | 支付方式选择、折扣计算 | Spring 的 Resource 加载 |
| 代理模式 | AOP、RPC 远程调用 | Spring AOP、MyBatis Mapper |
| 观察者模式 | 事件驱动、消息通知 | Spring Event、Guava EventBus |
| 模板方法 | 定义流程骨架,子类实现细节 | Spring 的 AbstractApplicationContext |
| 装饰器模式 | 动态增强功能 | Java I/O 流(BufferedInputStream) |
| 适配器模式 | 接口兼容转换 | Spring MVC 的 HandlerAdapter |
四、常见误区
这块当年坑了不少人,包括我自己——
- 过度设计:不是每个类都需要套设计模式。简单逻辑用
if-else就够了,硬套策略模式反而增加复杂度。设计模式是解决问题的工具,不是炫技的手段。 - 生搬硬套:设计模式要结合具体场景灵活变通,而不是照着书上的 UML 图一模一样地写。实际项目中的设计模式往往是简化版或组合使用的。
- 为了面试背模式:面试官真正想听的是你 在什么场景下,遇到了什么问题,选择了什么模式,为什么选它。能说出这个思考过程,比背 23 种模式的名字强 100 倍。
面试高频追问
-
追问:你项目中用到了哪些设计模式?能举个具体例子吗?
- 这是必问的。建议提前准备 2-3 个真实案例,按 "场景 → 问题 → 方案 → 效果" 的结构来答。
-
追问:设计模式会不会导致代码复杂度增加?怎么平衡?
- 关键看场景。复杂度要从整体来看——短期可能增加类的数量,但长期维护成本会降低。判断标准很简单:如果引入设计模式后,后续需求变更时改的代码变少了,那就是值得的。
-
追问:Spring 框架中用到了哪些设计模式?
- 这个问题太经典了。单例(Bean 默认作用域)、工厂(
BeanFactory)、代理(AOP)、模板方法(JdbcTemplate)、观察者(ApplicationEvent)、适配器(HandlerAdapter)……Spring 简直就是设计模式的教科书。
- 这个问题太经典了。单例(Bean 默认作用域)、工厂(
常见面试变体
- "说几个你熟悉的设计模式,结合项目讲讲"
- "设计模式的六大设计原则是什么?"
- "Spring 中用到了哪些设计模式?"
- "单例模式有哪些实现方式?各有什么优缺点?"
记忆口诀
三大类:创建(建)、结构(拼)、行为(动)—— "建拼动"
七大原则:单一开闭里、接口依赖迪、合成复用七—— "单开里、接依迪、合复七"
总结
设计模式是前辈们踩了无数坑之后总结出的最佳实践,核心价值在于 用成熟的方案解决反复出现的设计问题。面试时别背定义,结合项目经验、说出你选模式的思考过程,才是面试官真正想听的。
