面试指南

设计模式与编码

面试权重:★★ | 适用级别:P7/P8+ | 预计复习时间:1周

概览

面试权重:★★ | 适用级别:P7/P8+ | 预计复习时间:1周

这一章真正考的不是“能背出 23 种模式”,而是你能否说明什么时候该抽象、为什么这么设计、以及模式如何在业务和框架里落地。

建议用法

正文用于建立“问题 -> 设计原则 -> 模式选型 -> 框架映射”的理解链路;高频题用于压缩成 30 秒口述。复习时优先把相近模式成对记忆,比如策略 vs 模板方法、装饰器 vs 代理、工厂方法 vs 抽象工厂。

一、知识体系

1. 设计原则(SOLID) ★★★

1.1 SOLID原则

S — 单一职责原则(SRP)
  • 核心结论
    • 单一职责不是“一个类只写一个方法”,而是“一个模块只承受一类变化原因”。
  • 原理展开
    • 如果一个类同时负责参数校验、业务编排、持久化、通知下游,那么只要任一环节变化,这个类都要改,耦合度会快速上升。
    • SRP 的收益是降低变更波及面,提升可测试性和可替换性。
  • 面试怎么答
    • “我理解的单一职责是按变化原因拆分,而不是机械按功能点切类。比如支付服务里的风控、路由、渠道调用、回调通知就不应该全堆在一个 Service 里。”
  • 易错点
    • 过度拆分类也会让系统碎片化,SRP 不是无限拆分。
O — 开闭原则(OCP)
  • 核心结论
    • 对扩展开放、对修改关闭,本质是通过抽象把变化点提前隔离出来。
  • 原理展开
    • 最常见落地手法是接口、多态、策略注册表、插件机制,而不是硬背概念。
  • 面试怎么答
    • “开闭原则不是说永远不改旧代码,而是新增变化时优先通过扩展接入,避免频繁修改稳定主流程。”
  • 易错点
    • 不要为了追求 OCP 提前做大量并不存在的抽象,这会违反 YAGNI。
L — 里氏替换原则(LSP)
  • 核心结论
    • 子类能替换父类而不破坏调用方预期,重点是行为契约一致。
  • 原理展开
    • 如果父类承诺“调用一定成功”,子类却偷偷抛更多异常;或者父类支持全部输入,子类却收紧条件,都属于违背 LSP。
  • 面试怎么答
    • “LSP 不是语法上的继承关系,而是语义上的可替换性。子类不能破坏父类的前置条件、后置条件和不变量。”
  • 易错点
    • 继承不等于可复用。很多不合适的继承,本质上就是 LSP 已经被破坏了。
I — 接口隔离原则(ISP)
  • 核心结论
    • 客户端不应该依赖它不需要的方法,接口应该小而专。
  • 原理展开
    • 大接口通常导致“实现类被迫实现无关方法”“调用方依赖了不需要的能力”,最终演变成僵硬设计。
  • 面试怎么答
    • “接口隔离的目标是减少无效依赖。尤其在跨服务边界和 SDK 设计里,接口越聚焦,后续演进越稳。”
D — 依赖倒置原则(DIP)
  • 核心结论
    • 高层模块和低层模块都应该依赖抽象,而不是高层直接依赖具体实现。
  • 原理展开
    • DIP 是工厂、策略、DDD 分层、IOC 容器得以成立的重要基础。
  • 面试怎么答
    • “依赖倒置让业务编排依赖接口,具体实现由容器或工厂注入。这样高层流程稳定,底层实现才有替换空间。”
  • 易错点
    • 依赖抽象不等于项目里所有类都必须抽接口。稳定且不会替换的简单实现,可以保留直接依赖。

1.2 其他重要原则 ★★

  • DRY
    • 核心结论:避免重复的不是代码行数,而是知识和规则的重复来源。
  • KISS
    • 核心结论:优先选最直接、团队能长期维护的方案。
  • YAGNI
    • 核心结论:不要为假想需求提前建复杂扩展点。
  • 组合优于继承
    • 核心结论:组合更灵活、更容易控制边界,也更不容易破坏父类契约。
  • 迪米特法则
    • 核心结论:模块之间只暴露必要交互,减少“深链式调用”。

2. 创建型模式 ★★

2.1 单例模式(Singleton) ★★★

  • 核心结论
    • 单例的价值在于控制全局唯一实例和统一访问入口,但它天然带来生命周期、测试隔离和隐藏依赖问题。
常见实现方式
  • 饿汉式:类加载即创建,简单但可能提前占资源。
  • 懒汉式:延迟初始化,但线程安全实现容易出错。
  • DCL(双重检查锁):volatile + synchronized,兼顾延迟加载和并发安全。
  • 静态内部类:利用类加载的线程安全特性实现延迟初始化。
  • 枚举单例:最稳妥,天然防反射与反序列化破坏。
DCL(双重检查锁):volatile + synchronized
  • 原理展开
    • new 不是原子操作,可能发生“分配内存 -> 引用赋值 -> 对象初始化”的指令重排。
    • 没有 volatile 时,其他线程可能读到一个“引用非空但对象未初始化完成”的实例。
  • 面试怎么答
    • “DCL 的难点不在双重 if,而在 volatile 要禁止重排序,否则会拿到半初始化对象。”
  • 易错点
    • 不要只说 volatile 保证可见性,面试里最好补上“禁止重排序”。
Spring Bean默认单例的实现(三级缓存)
  • 核心结论
    • Spring 的单例不是 GoF 单例模式的简单翻版,它更像是 IOC 容器托管下的单例作用域。
  • 面试怎么答
    • “Spring 默认单例的重点在容器生命周期和依赖注入,不只是‘全局只 new 一次’。三级缓存主要是为了解循环依赖场景中的提前暴露。”

2.2 工厂模式(Factory) ★★★

  • 核心结论
    • 工厂模式解决的是“对象创建逻辑和使用逻辑解耦”,不只是把 new 换个地方写。
简单工厂 / 工厂方法 / 抽象工厂
  • 原理展开
    • 简单工厂:一个工厂里根据参数分支创建所有产品,适合产品少、变化少的场景。
    • 工厂方法:每个产品或产品类型有自己的创建入口,符合开闭原则。
    • 抽象工厂:一次创建一组有关联的产品族,适合主题化、平台化、跨环境适配。
  • 面试怎么答
    • “简单工厂适合控制入口,工厂方法适合扩展单个产品,抽象工厂适合扩展整组产品族。三者复杂度和扩展维度不同。”
  • 易错点
    • 不要把“创建对象”都叫工厂。关键是有没有把创建规则抽离成稳定边界。
Spring中的应用:BeanFactory、FactoryBean
  • 核心结论
    • BeanFactory 是容器级工厂,FactoryBean 是让某个 Bean 的创建逻辑也工厂化。
  • 面试怎么答
    • “前者是 Spring 的整体创建机制,后者是把单个复杂对象的创建过程托管给一个特殊 Bean。”

2.3 建造者模式(Builder) ★★

  • 核心结论
    • Builder 适合“参数多、构建过程分步、对象需要保持创建后不可变或一致性”的场景。
  • 原理展开
    • Builder 把复杂对象的装配过程显式化,避免 telescoping constructor。
    • Lombok @Builder 是语法层简化,但设计意图仍然是“分步构建复杂对象”。
  • 面试怎么答
    • “如果对象参数多且可选项多,我会优先考虑 Builder;如果还存在固定的构建顺序,再考虑引入 Director。”
  • 易错点
    • 不要把链式 setter 当成完整 Builder。真正的 Builder 通常会在 build() 时做一致性校验。

2.4 原型模式(Prototype) ★

  • 核心结论
    • 原型模式适合复制成本高或想快速生成相似对象的场景,但 Java 里 Cloneable 体验并不理想。
  • 原理展开
    • 浅拷贝只复制外壳,引用字段仍共享。
    • 深拷贝要递归复制对象图,业务里更常见的做法是显式拷贝构造或映射转换。
  • 面试怎么答
    • “原型模式的核心是复制而不是创建,但 Java 里我通常不会直接推荐 clone(),而是更倾向显式拷贝。”

3. 结构型模式 ★★

3.1 代理模式(Proxy) ★★★

  • 核心结论
    • 代理模式的核心意图是控制访问、增强横切能力,而不是简单包装一下对象。
静态代理
  • 原理展开
    • 代理类和目标类实现同一接口,适合逻辑简单、类型数量少的场景。
JDK动态代理:基于接口(InvocationHandler)
  • 核心结论
    • 依赖接口,生成代理对象时把方法调用统一转发给 InvocationHandler
CGLIB动态代理:基于继承(MethodInterceptor)
  • 核心结论
    • 通过生成子类织入增强逻辑,适用于没有接口的类,但不能代理 final 类和 final 方法。
JDK vs CGLIB 区别
  • 面试怎么答
    • “JDK 动态代理基于接口,侵入性低;CGLIB 基于继承,适用面更广但受 final 限制。Spring AOP 会根据目标类型选择,现代版本也常统一偏向 CGLIB 以减少行为差异。”
  • 易错点
    • 不要把代理模式和装饰器模式混为一谈。二者结构相似,但意图不同。
Spring AOP的实现:JDK代理(接口) + CGLIB(类)
  • 核心结论
    • AOP 是代理模式在框架里的经典落地,重点不是“代理本身”,而是把事务、日志、权限这类横切关注点抽出来。

3.2 装饰器模式(Decorator) ★★

  • 核心结论
    • 装饰器解决的是“在不改原类的前提下叠加能力”,适合能力可组合扩展的场景。
  • 原理展开
    • Java IO 流是典型案例,BufferedInputStreamDataInputStream 都是在原始流上叠加能力。
  • 面试怎么答
    • “装饰器强调能力叠加,代理强调访问控制或增强。结构可能像,但设计意图不同。”

3.3 适配器模式(Adapter) ★★

  • 核心结论
    • 适配器不是为了“设计得优雅”,而是为了隔离不兼容接口,减少调用方被外部模型污染。
  • 原理展开
    • 类适配器基于继承,受单继承限制。
    • 对象适配器基于组合,更灵活,也更常见。
  • 面试怎么答
    • “我在业务里几乎都用对象适配器,因为它能把外部 DTO 和内部领域模型清晰隔离开。”
  • 易错点
    • 适配器不是 DTO 转换工具的另一个名字。关键是要隔离接口差异和依赖边界。

3.4 其他结构型 ★

  • 外观模式(Facade)
    • 核心结论:对复杂子系统提供统一入口,适合对外暴露简单 API。
  • 桥接模式(Bridge)
    • 核心结论:把抽象和实现两个变化维度拆开,避免类爆炸。
  • 组合模式(Composite)
    • 核心结论:用树形结构统一处理单个对象和组合对象。
  • 享元模式(Flyweight)
    • 核心结论:通过共享内部状态减少对象数量,典型如 Integer 缓存池、字符串常量池。

4. 行为型模式 ★★

4.1 策略模式(Strategy) ★★★

  • 核心结论
    • 策略模式解决的是“同一目标下存在多种可替换算法或处理路径”,它对消除大段 if-else/switch 很有效。
if-else/switch消除利器
  • 原理展开
    • 先定义统一策略接口,再把每种规则封装为独立实现,最后通过注册表、工厂或 IOC 容器按 key 路由。
  • 面试怎么答
    • “策略模式不是为了炫技,而是把分支逻辑从主流程里抽出来,让新增策略不必反复改旧逻辑。”
  • 易错点
    • 分支很少、变化频率很低的场景,直接 if-else 可能更简单,不必强行上策略。
Spring中的应用:多实现注入Map/List
  • 核心结论
    • Spring 容器天然适合做策略注册中心,通过 Map<String, Strategy> 就能把实现收集起来。

4.2 模板方法模式(Template Method) ★★

  • 核心结论
    • 模板方法适合“流程稳定、步骤可变”的场景,通过继承约束算法骨架。
  • 原理展开
    • 父类定义固定主流程,子类实现差异步骤或钩子方法。
    • JdbcTemplateHttpServlet、AQS 都体现了这一思路。
  • 面试怎么答
    • “模板方法强调流程骨架稳定,策略模式强调算法整体可替换。一个偏继承,一个偏组合。”
  • 易错点
    • 当变化点很多、子类分支越来越多时,模板方法会变僵硬,此时往往要转向组合或策略。

4.3 观察者模式(Observer) ★★

  • 核心结论
    • 观察者模式解决的是一对多通知,重点是解耦事件发送方和处理方。
  • 原理展开
    • Spring 事件机制、MQ 的发布订阅、领域事件扩展都可以从观察者角度理解。
  • 面试怎么答
    • “观察者适合异步扩展和跨模块通知,但要注意事件幂等、失败补偿和链路可观测性。”

4.4 责任链模式(Chain of Responsibility) ★★

  • 核心结论
    • 责任链适合把一串处理步骤按顺序组织起来,让每个节点只关心自己的处理逻辑和是否向后传递。
  • 原理展开
    • Servlet Filter、Spring Interceptor、Netty Pipeline、Sentinel SlotChain 都是典型案例。
  • 面试怎么答
    • “责任链特别适合校验、鉴权、限流、风控这类串行处理流程,因为每个节点都能独立扩展和插拔。”
  • 易错点
    • 责任链不等于所有流程都该拆成链。链路太长会让问题定位和执行开销变差。

4.5 其他行为型 ★

  • 迭代器模式(Iterator)
    • 核心结论:封装集合遍历细节。
  • 状态模式(State)
    • 核心结论:把状态切换和状态行为显式建模,适合订单流转、审批流。
  • 命令模式(Command)
    • 核心结论:把请求封装成对象,便于排队、记录、回放。
  • 中介者模式(Mediator)
    • 核心结论:通过中心对象协调交互,减少对象之间网状依赖。

5. 框架中的设计模式 ★★★

5.1 Spring中的设计模式

模式应用
工厂BeanFactory、FactoryBean
单例默认 Bean 作用域
代理AOP(JDK/CGLIB)
模板方法JdbcTemplate、RestTemplate
观察者ApplicationEvent
适配器HandlerAdapter
策略多实现注入、资源加载策略
责任链Filter / Interceptor 链
  • 面试怎么答
    • “Spring 最值得讲的不是某一个模式,而是 IOC、AOP、模板、事件机制这些模式如何协同形成一整套扩展框架。”

5.2 MyBatis中的设计模式

  • 建造者:SqlSessionFactoryBuilder
  • 工厂:SqlSessionFactory
  • 代理:Mapper 接口的 JDK 动态代理
  • 模板方法:BaseExecutor

6. DDD领域驱动设计补充 ★★★(P8+)

6.1 分层架构演进

  • 核心结论
    • 从传统三层走向 DDD 四层,不是为了“架构更高级”,而是为了让核心业务规则从基础设施细节中解耦。
  • 原理展开
    • UI 层负责交互和接口适配。
    • Application 层负责用例编排,应该保持薄。
    • Domain 层承载业务规则和领域行为。
    • Infrastructure 层负责数据库、RPC、MQ、缓存等技术实现。
  • 面试怎么答
    • “DDD 四层最关键的是依赖方向,Domain 不依赖外层具体实现,这样业务规则才能长期稳定演进。”

6.2 贫血模型 vs 充血模型 ★★★

  • 核心结论
    • 贫血模型适合简单 CRUD,充血模型更适合规则复杂、约束强的核心域。
  • 原理展开
    • 贫血模型把业务逻辑放在 Service,Entity 只做数据载体。
    • 充血模型把规则校验、状态变更、领域不变量收回到实体或聚合内部。
  • 面试怎么答
    • “不是所有系统都要强行充血。更现实的做法是核心域逐步充血,边缘 CRUD 模块保持贫血。”
  • 易错点
    • 充血模型不等于把所有 Service 代码搬到 Entity 里。聚合边界和职责仍要清晰。

6.3 防腐层(Anti-Corruption Layer) ★★

  • 核心结论
    • 防腐层的职责是阻断外部模型和概念污染内部领域,不只是做字段映射。
  • 原理展开
    • 常见落地是接口隔离 + 适配器 + DTO/VO 转换 + 异常语义统一。
  • 面试怎么答
    • “外部系统随时可能变,防腐层就是在边界处把变化拦住,让内部模型保持稳定。”

二、高频面试题

基础级(P7必答)

  1. 单例模式有几种实现?为什么推荐枚举单例?DCL 为什么需要 volatile
  • 30秒答法
    • 常见实现有饿汉、懒汉、DCL、静态内部类和枚举。枚举单例最稳,因为天然防反射和反序列化破坏。DCL 里的 volatile 关键是禁止重排序,避免读到半初始化对象。
  • 关键词
    • 枚举单例
    • 反序列化
    • 指令重排
    • volatile
  • 追问提醒
    • 常追问静态内部类为什么线程安全、Spring 单例和 GoF 单例有什么区别。
  1. JDK 动态代理和 CGLIB 的区别?Spring AOP 用的哪个?
  • 30秒答法
    • JDK 动态代理基于接口,CGLIB 基于继承。前者要求目标类有接口,后者不能代理 final 类和 final 方法。Spring 会根据目标类型和配置选择代理方式,现代项目里常统一偏向 CGLIB。
  • 关键词
    • InvocationHandler
    • MethodInterceptor
    • 接口代理
    • 继承代理
  • 追问提醒
    • 继续准备回答为什么自调用会导致 AOP 失效。
  1. 策略模式如何消除 if-else?在你的项目中怎么用的?
  • 30秒答法
    • 把每种分支规则封装成独立策略,实现统一接口,再通过工厂或容器按 key 路由选择。这样新增渠道只需要加新策略,不需要反复修改主流程。
  • 关键词
    • 策略接口
    • 注册表
    • key 路由
    • 扩展点
  • 追问提醒
    • 常追问策略和工厂怎么配合、分支少时还要不要用策略。
  1. 工厂模式的几种形式?Spring 中怎么体现的?
  • 30秒答法
    • 简单工厂适合统一创建入口,工厂方法适合扩展单个产品,抽象工厂适合扩展一整组产品族。Spring 里 BeanFactory 是工厂机制核心,FactoryBean 则是把复杂 Bean 的创建过程也工厂化。
  • 关键词
    • 简单工厂
    • 工厂方法
    • 抽象工厂
    • FactoryBean
  • 追问提醒
    • 常继续问 BeanFactoryApplicationContext 的关系。
  1. 说说你在项目中用过的设计模式?解决了什么问题?
  • 30秒答法
    • 最稳的回答方式是按“场景问题 -> 选了什么模式 -> 为什么这样选 -> 收益”来讲。比如策略 + 工厂消除支付渠道分支,模板方法统一任务执行框架,责任链处理风控校验,观察者做异步通知解耦。
  • 关键词
    • 场景驱动
    • 选型理由
    • 收益
    • 权衡
  • 追问提醒
    • 面试官通常会追问你为什么不用别的模式。
  1. SOLID 原则分别是什么?举例说明开闭原则?
  • 30秒答法
    • SOLID 分别是单一职责、开闭、里氏替换、接口隔离、依赖倒置。开闭原则的典型例子是新增支付方式时只增加新的策略实现,不改原有支付编排逻辑。
  • 关键词
    • SRP
    • OCP
    • LSP
    • DIP
  • 追问提醒
    • 继续准备“过度设计是不是违反 YAGNI”这类追问。
  1. 观察者模式和事件驱动架构有什么关系?在项目中怎么用的?
  • 30秒答法
    • 观察者模式是一对多通知的基础模型,事件驱动架构则把这种思想扩展到系统层面。项目里常用它处理支付成功、订单状态变更、消息通知这类异步扩展场景。
  • 关键词
    • 发布订阅
    • 领域事件
    • 异步解耦
    • 幂等
  • 追问提醒
    • 常追问同步事件和 MQ 异步事件如何选择。
  1. 责任链模式在项目中怎么应用?和 Filter 链有什么关系?
  • 30秒答法
    • 责任链是把多个处理节点串起来依次执行,Filter 链就是它的典型实现。项目里它特别适合做鉴权、校验、风控、限流等可插拔流程。
  • 关键词
    • 链式处理
    • Filter
    • Interceptor
    • 可插拔
  • 追问提醒
    • 常继续问如何中断链路、如何保证执行顺序和观测性。
  1. 模板方法模式和策略模式怎么选?区别是什么?
  • 30秒答法
    • 模板方法适合流程骨架稳定、局部步骤可变的场景,靠继承实现;策略模式适合整体算法可替换的场景,靠组合实现。前者强调约束流程,后者强调运行时切换。
  • 关键词
    • 继承
    • 组合
    • 流程骨架
    • 算法替换
  • 追问提醒
    • 面试官常要求你结合实际业务举例,而不是只讲定义。
  1. 建造者模式的链式调用和 Director 模式有什么区别?
  • 30秒答法
    • 链式 Builder 更灵活,适合多数业务对象构建;Director 适合构建顺序固定、步骤受约束的复杂对象。简单对象用链式即可,复杂装配再考虑 Director。
  • 关键词
    • Fluent Builder
    • Director
    • 构建顺序
    • 校验
  • 追问提醒
    • 可以顺带补充不可变对象和 Builder 的关系。
  1. 适配器模式在实际项目中有什么应用?类适配和对象适配怎么选?
  • 30秒答法
    • 适配器常用于新老系统接口不兼容、外部 SDK 接入、领域模型隔离。实际项目里更推荐对象适配器,因为组合更灵活,也不会受单继承限制。
  • 关键词
    • 新老系统兼容
    • 对象适配器
    • 组合
    • 边界隔离
  • 追问提醒
    • 常追问防腐层和适配器的关系。

进阶级(P8+深挖)

  1. 贫血模型和充血模型的区别?你的项目用的是哪种?为什么?
  • 30秒答法
    • 贫血模型把逻辑放在 Service,适合简单 CRUD;充血模型把规则收回领域对象,适合复杂核心域。更现实的做法是核心模块逐步充血,边缘模块保持轻量。
  • 关键词
    • 贫血
    • 充血
    • 领域规则
    • 核心域
  • 追问提醒
    • 常追问聚合根、领域服务和应用服务怎么划分。
  1. 如何从传统三层架构演进到 DDD 四层架构?
  • 30秒答法
    • 先从最复杂的核心模块开始,把业务规则从 Service 下沉到 Domain,再用 Application 层做用例编排,Infrastructure 实现技术细节。关键不是一次性重构,而是先把依赖方向理顺。
  • 关键词
    • 渐进式演进
    • Domain
    • Application
    • 依赖倒置
  • 追问提醒
    • 常继续问 Repository 接口放哪层、事务边界怎么定。
  1. 你怎么判断该用继承还是组合?举实际例子。
  • 30秒答法
    • 默认优先组合,因为更灵活、边界更清晰。只有明确 is-a 且不会破坏父类契约时才用继承。比如 BufferedInputStream 更适合组合装饰,而不是继承一层层堆能力。
  • 关键词
    • is-a
    • 组合优先
    • LSP
    • 装饰器
  • 追问提醒
    • 准备一个你项目里“曾经错误继承、后面改成组合”的例子会更有说服力。
  1. 设计一个可扩展的支付系统,用到哪些设计模式?
  • 30秒答法
    • 支付渠道选择用策略模式,渠道实例创建用工厂,公共流程用模板方法,风控和校验用责任链,支付成功后的通知用观察者或事件驱动。这套组合比单一模式更贴近真实项目。
  • 关键词
    • 策略
    • 工厂
    • 模板方法
    • 责任链
  • 追问提醒
    • 常追问幂等、状态机和失败补偿怎么接进来。
  1. 微服务中的防腐层怎么设计?
  • 30秒答法
    • 在外部系统边界增加一层适配与转换逻辑,把外部 DTO、错误码、状态语义转换成本域模型,避免外部概念直接侵入内部领域。核心是隔离变化,而不是单纯写几个 converter。
  • 关键词
    • 防腐层
    • 边界
    • 适配器
    • 模型转换
  • 追问提醒
    • 可继续准备接口隔离、灰度兼容和测试替身设计。

三、实战场景题(P8+重点)

  1. 重构遗留代码:接手一个 3000 行的 Service 类,如何重构?用什么模式?
  • 回答框架
    • 先识别职责边界和变化点,拆出编排、校验、持久化、通知等模块。
    • 再决定哪些地方适合策略、模板方法、责任链或防腐层。
    • 最后通过测试兜底、灰度替换、逐步下沉逻辑,避免一次性重构爆炸。
  • 核心关注点
    • 先拆职责,再谈模式。
    • 模式服务于问题,不是为了把 3000 行代码拆成 30 个类。
  1. 规则引擎:业务有大量规则判断(几十个 if-else 嵌套),如何设计更优雅的方案?
  • 回答框架
    • 先判断规则是否稳定、是否需要动态配置。
    • 静态规则优先考虑策略 + 工厂 + 责任链;动态规则再评估规则引擎或 DSL。
    • 加上优先级、短路、灰度和观测能力。
  • 核心关注点
    • 不要一看到复杂规则就上 Drools。
    • 规则复杂度、可运营性和调试成本要一起评估。
  1. 插件架构:需要设计一个支持插件扩展的系统,如何利用 SPI 和设计模式实现?
  • 回答框架
    • 先定义稳定扩展点接口,再用 SPI 或注册中心发现插件实现。
    • 核心流程可用模板方法,插件选择可用工厂或策略,插件链路可用责任链。
    • 补齐隔离、版本兼容、生命周期和异常兜底。
  • 核心关注点
    • 扩展点接口必须稳定。
    • 插件失效不能拖垮主流程。
  1. 领域建模:对一个电商订单系统进行领域建模,识别聚合、实体、值对象。
  • 回答框架
    • 先按业务能力切子域,再识别订单、支付、履约、库存等核心对象。
    • 明确聚合根和一致性边界,比如订单作为聚合根统一控制状态流转。
    • 区分实体和值对象,并把状态变更规则收回聚合内部。
  • 核心关注点
    • 不要把数据库表直接等同为领域对象。
    • 聚合边界要围绕一致性而不是围绕页面模块。

四、学习资源推荐

书籍

  • 《Head First 设计模式》:适合快速建立模式直觉。
  • 《设计模式:可复用面向对象软件的基础》:经典原著,适合查定义。
  • 《重构:改善既有代码的设计》:更贴近工程落地。
  • 《领域驱动设计》:适合理解模式和领域建模的结合。

博客/文章

  • Refactoring.Guru:图示和意图解释清晰。
  • 极客时间《设计模式之美》:更偏工程实战。
  • 极客时间《DDD 实战课》:适合从模式走向领域建模。

视频

  • 尚硅谷图解 Java 设计模式:适合快速扫盲。
  • B 站设计模式实战类课程:适合配合项目案例理解。

On this page

一、知识体系1. 设计原则(SOLID) ★★★1.1 SOLID原则S — 单一职责原则(SRP)O — 开闭原则(OCP)L — 里氏替换原则(LSP)I — 接口隔离原则(ISP)D — 依赖倒置原则(DIP)1.2 其他重要原则 ★★2. 创建型模式 ★★2.1 单例模式(Singleton) ★★★常见实现方式DCL(双重检查锁):volatile + synchronizedSpring Bean默认单例的实现(三级缓存)2.2 工厂模式(Factory) ★★★简单工厂 / 工厂方法 / 抽象工厂Spring中的应用:BeanFactory、FactoryBean2.3 建造者模式(Builder) ★★2.4 原型模式(Prototype) ★3. 结构型模式 ★★3.1 代理模式(Proxy) ★★★静态代理JDK动态代理:基于接口(InvocationHandler)CGLIB动态代理:基于继承(MethodInterceptor)JDK vs CGLIB 区别Spring AOP的实现:JDK代理(接口) + CGLIB(类)3.2 装饰器模式(Decorator) ★★3.3 适配器模式(Adapter) ★★3.4 其他结构型 ★4. 行为型模式 ★★4.1 策略模式(Strategy) ★★★if-else/switch消除利器Spring中的应用:多实现注入Map/List4.2 模板方法模式(Template Method) ★★4.3 观察者模式(Observer) ★★4.4 责任链模式(Chain of Responsibility) ★★4.5 其他行为型 ★5. 框架中的设计模式 ★★★5.1 Spring中的设计模式5.2 MyBatis中的设计模式6. DDD领域驱动设计补充 ★★★(P8+)6.1 分层架构演进6.2 贫血模型 vs 充血模型 ★★★6.3 防腐层(Anti-Corruption Layer) ★★二、高频面试题基础级(P7必答)进阶级(P8+深挖)三、实战场景题(P8+重点)四、学习资源推荐书籍博客/文章视频