设计模式

目录概述

设计模式是程序员的内功心法,也是面试中区分"写代码的"和"懂设计的"关键战场。

很多人背过单例、工厂、代理,但面试官一问"你用过什么设计模式?什么场景下不适合用?",就开始语无伦次。

这一模块不教你背模式,而是带你理解每种模式的适用场景工程代价真实踩坑,让你在面试中能说出"为什么用"和"为什么不用"。

内容范围

类别涵盖模式面试频率
创建型单例、工厂方法、抽象工厂、建造者、原型🔴
结构型代理、装饰器、适配器、桥接、组合、外观🔴
行为型策略、观察者、模板方法、职责链、迭代器🔴
进阶责任链模式、状态机模式、解释器模式🟡

学习路径指引

P5 阶段:能识别、能说出用途

记住 23 种模式的名称和基本结构,能在代码中认出它们。

核心要求

  • 单例:饿汉 vs 懒汉,双重检查锁的原理
  • 工厂:简单工厂、工厂方法、抽象工厂的区别
  • 策略:消除 if-else 的典型场景
  • 代理:静态代理 vs JDK 动态代理 vs CGLIB

P6 阶段:能应用、能解决实际问题

能在实际项目中主动使用设计模式,而非事后重构。

核心要求

  • Spring 框架中用到了哪些设计模式( factory、proxy、template method)
  • MyBatis 中用到了哪些设计模式(解释器、装饰器)
  • 能结合业务场景设计自己的模式组合

P7 阶段:能权衡、能做架构决策

知道什么时候该用模式,什么时候该保持简单。

核心要求

  • 过度设计的代价是什么
  • 充血模型 vs 贫血模型的选择
  • 领域驱动设计(DDD)中的模式应用

核心能力矩阵

能力项P5P6P7
识别常见模式
说出模式的 UML 结构
解释模式解决了什么问题-
在项目中主动应用-
权衡:模式 vs 简单实现--
设计新模式解决特定问题--

面试题分级

🔴 高频必考

单例模式

  • 饿汉、懒汉、双重检查锁、枚举单例
  • 为什么双重检查锁要用 volatile
  • 序列化破坏单例怎么解决?

工厂模式

  • 三种工厂的区别和适用场景
  • Spring 的 BeanFactory 用了什么设计模式?

代理模式

  • JDK 动态代理的原理,缺点是什么?
  • CGLIB 相比 JDK 代理的优势在哪里?
  • Spring AOP 用的是哪种代理?

🟡 中频常考

策略模式

  • 消除 if-else 的典型场景
  • 策略模式和命令模式的区别

观察者模式

  • JDK 提供的 ObservableObserver 为什么被废弃?
  • Spring 事件机制用的是什么模式?

模板方法模式

  • JDBC Template 用的是什么设计模式?
  • HttpServletservice() 方法体现了什么设计思想?

🟢 低频了解

  • 责任链模式:Netty 中的 pipeline
  • 状态机模式:订单状态流转
  • 解释器模式:SpEL 表达式解析

生产避坑

过度设计的坑

很多开发团队踩过这个坑:学完设计模式后,什么都想套模式,最后代码里一堆抽象类和接口,改一个 bug 要改三个地方。

典型案例: 一个简单的数据导出功能,被一个实习生套了策略模式、工厂模式、装饰器模式,加了五层抽象。后来维护这个功能的同学差点掀桌子。

模式选错人的坑

单例模式是面试送分题,但很多人不知道单例在 Spring 中其实有问题:

  • 单例Bean持有原型Bean怎么办?
  • 单例模式导致的内存泄漏怎么排查?

代理模式被滥用的坑

Spring AOP 是好东西,但有人在 Service 层写了 20 个切面,导致调试困难、事务失效都不知道。

工程选型

场景推荐模式不推荐
只需要一个实例枚举单例懒汉双检(容易被面试追问)
创建对象逻辑复杂工厂方法直接 new(暴露构造函数)
多种算法切换策略模式if-else 堆砌
统一入口封装外观模式直接在业务代码里调用子系统
方法增强代理模式继承(单继承限制)

【架构权衡】 设计模式的本质是解决重复问题。如果一个问题你只遇到一次,或者用简单代码就能解决,不要强行套模式。记住:KISS 原则永远是第一位的。