Skip to Content
面试题库Design Patterns设计模式

大家都知道23种设计模式。但从面试和业务落地的角度看:

  • 首先,根本用不上这么多的设计模式。
  • 其次,设计模式根本不是一门“背术语”的学科,它真正考的是:当代码开始变复杂时,你有没有能力把变化点隔离出来,把耦合拆开,把扩展性留出来。

设计模式这章,真正的结论其实很简单:不是先学会模式再写代码,而是先遇到变化和复杂度,再知道该用哪种模式去消化它。

首先,设计模式不是为了炫技,而是为了处理高频的软件设计问题。它解决的核心矛盾,永远是变化和复杂度

在创建对象这条线上,最重要的是:

  • 单例解决“全局唯一”
  • 工厂解决“创建逻辑解耦”

在组织类关系这条线上,最重要的是:

  • 代理解决“控制访问”
  • 装饰器解决“动态增强”
  • 适配器解决“接口兼容”

在组织行为流程这条线上,最重要的是:

  • 策略解决“算法可替换”
  • 模板方法解决“流程骨架固定,局部步骤可变”
  • 观察者解决“一变多通知”
  • 责任链解决“请求沿链路逐步处理”

这一切的底层思想,最后都能回到开闭原则、依赖倒置、里氏替换这些面向对象设计原则上。

所以设计模式这章,主线其实是:

  1. 为什么需要设计模式?
  2. 创建对象时常见的问题怎么解?
  3. 组织类关系时常见的问题怎么解?
  4. 组织行为流程时常见的问题怎么解?

为什么需要模式?

设计模式本质上不是“高级写法”,而是前人总结出来的一套高频设计问题的通用解法

当系统开始变大时,我们最常遇到的几个问题其实非常朴素:

  • 对象创建逻辑越来越复杂;
  • if-else 越来越多;
  • 一个类承担了太多职责;
  • 业务变种越来越多,改一处牵一片;
  • 新需求不是加功能,而是和旧功能交错着长。

所以设计模式的价值,从来不是“代码看起来高级”,而是:

  • 降低耦合
  • 提高可扩展性
  • 隔离变化点
  • 让复杂系统更容易演化

相关阅读:

设计模式真正学到最后,离不开三条底层原则:

  • 开闭原则:对扩展开放,对修改关闭。
  • 依赖倒置:依赖抽象,不依赖具体实现。
  • 里氏替换:子类必须能替换父类而不破坏原有语义。

这些原则不是单独考的理论,它们其实就是后面所有模式的底层哲学

相关阅读:


对象到底该怎么创建

很多系统一开始写得很简单,直接 new 就完了。但当对象创建过程开始变复杂,比如:

  • 初始化步骤很多;
  • 不同环境要创建不同实现;
  • 某些对象必须全局唯一;
  • 一组产品要成套出现;

这时候直接 new 就不够用了。这个时候就引入了第一类设计模式了。

单例模式

单例的核心不是“语法写法”,而是回答一句话:这个对象是不是全局只需要一个?

典型场景包括:

  • 配置中心对象
  • 线程池管理器
  • 缓存管理器
  • 某些全局协调组件

相关阅读:

工厂模式

工厂模式本质上解决的是:对象创建逻辑不要散落在业务代码里。 你可以把它理解成“把 new 的复杂性封装起来”。

  • 简单工厂:一个工厂类根据条件返回不同产品。
  • 工厂方法:把“生产什么”这件事下放到不同工厂子类。
  • 抽象工厂:生产一整套相互关联的产品族。

所以这三者不是“谁更高级”,而是应对复杂度的层级不一样。

相关阅读:

建造者模式

把复杂对象的「构建过程」和「内部表示」拆开,不用写一堆重载构造方法,链式调用优雅创建对象。

适用场景:对象属性特别多、创建步骤繁琐、参数组合灵活、不想写重叠重载构造器。比如:

  • 复杂实体(用户、订单参数很多字段)
  • 配置类、请求参数类
  • 创建过程固定,但内部部件可以自由组合

类关系怎么组织更灵活

当系统复杂之后,第二类问题往往不是“怎么创建对象”,而是“怎么在不改原始类的情况下扩功能”。

代理模式

代理模式的核心是:我不直接访问目标对象,而是通过一个中间层控制访问。

这类模式特别适合做:

  • 权限校验
  • 延迟加载
  • 远程调用封装
  • 事务、日志、监控增强

Spring AOP、RPC 框架代理、本地缓存代理,本质上都能往这一类里靠。

而且代理模式还可以顺便把静态代理和动态代理串起来:静态代理更直白,但容易类爆炸;动态代理更灵活,更适合框架化能力。

相关阅读:

  • 代理模式和装饰器模式有什么区别?静态代理和动态代理分别适合什么场景?

装饰器模式

装饰器模式和代理模式长得很像,所以特别容易混。

它们的共同点是都会包一层对象、都可能实现相同接口;但核心区别在于目的,代理更偏控制访问、装饰器更偏动态叠加功能。

最经典的思路是:原始对象不改,通过一层层装饰把额外能力套上去。Java IO 那一大串 InputStream / BufferedInputStream / DataInputStream,就是特别标准的装饰器思路。

相关阅读:

适配器模式

适配器模式本质上解决的是接口不兼容。适配器不是为了增强功能,而是为了让两个原本对不上的接口接上

当老系统有一套接口,新系统期待另一套接口,但你又不想改原始实现,这时候就可以做一层适配,把原有能力“翻译”成新接口能听懂的样子。


一段业务流程怎么设计得更可扩展

很多真实业务里,最麻烦的问题其实不是建模,而是行为流程越来越复杂。

比如:支付方式越来越多、审批规则越来越多、活动规则越来越多、同样一条主流程里,局部步骤会随场景变化。

这一类问题,最常见会落到策略、模板方法、观察者、责任链。

策略模式

策略模式特别适合解决:同一件事情有多种算法或处理方式,而且它们可以互相替换。

最典型场景:不同支付方式、不同优惠计算方式、不同路由规则、不同排序/过滤算法

它的核心思想是把算法抽出来,业务上下文只依赖抽象策略,不写一长串 if-else。

相关阅读:

模板方法模式

模板方法和策略经常一起考,因为它们都在解决“流程变化”问题。区别在于:

  • 策略模式是把整块算法外置,运行时替换。
  • 模板方法是把主流程固定住,只把某些步骤留给子类定制。

也就是说,模板方法更像“骨架稳定、局部可变”的模式。

比如一套标准下单流程、标准消息发送流程、标准风控流程,主干步骤不变,但某几步根据渠道不同可以覆写。

观察者模式

观察者模式特别适合“一变多通知”的场景。当一个对象状态变化时,需要通知很多依赖方,比如:

  • 订单状态变化通知积分、库存、消息模块
  • 配置变化通知多个监听器
  • 领域事件触发多个后续动作

这里最关键的理解是:观察者模式本质上是在做解耦通知

而它和发布订阅的区别,往往在于中间是否引入事件总线/消息代理。观察者通常更偏进程内直接订阅关系,发布订阅更容易进一步扩展成分布式消息模型。

相关阅读:

责任链模式

责任链模式特别适合:请求需要经过一串处理器,但到底谁处理、处理到哪一步,不希望在入口处写死。Spring MVC 的拦截器链、Servlet Filter 链,都是特别经典的责任链思想。

典型场景包括:过滤器链、拦截器链、审批流、风控规则链

它的核心是把处理节点串起来,让请求沿链条逐步传递。

  • 优点很明显:扩展处理节点很方便;符合开闭原则;把复杂判断拆散了;
  • 但也有缺点:链路太长时不好排查;顺序依赖会变重。

相关阅读:

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册