30、设计模式总结与面试指南:高频面试题、模式对比、如何选择设计模式

学完前面29章,你可能会有点晕——23种经典模式,加上各种变体,到底该怎么记?面试官问起来怎么答?实际项目里怎么选?

别急。这一章我不打算再讲新知识了。咱们坐下来,像复盘一个项目一样,把设计模式这整张地图捋一遍。我会结合我这些年面试别人、也被别人面试的经验,给你一份真正能用的“面试指南”和“选择手册”。

30.1 高频面试题Top 10

先说说面试。我面过不少人,也帮团队出过面试题。设计模式这块,面试官其实不爱考“背诵题”。他们更想听你讲“为什么用”和“怎么用”。

核心原则:面试官问设计模式,不是考你背了多少种,而是看你有没有“模式思维”。

下面这10道题,是我统计了近百场面试后总结出来的高频题。每道题我都附上了“面试官想听什么”。

序号 高频面试题 考察点 回答建议
1 单例模式有几种写法?哪种最安全? 线程安全、反序列化 枚举单例最安全,但实际项目中我常用静态内部类
2 工厂模式、抽象工厂模式有什么区别? 产品族 vs 产品等级 画个图讲清楚,举一个数据库驱动的例子
3 代理模式和装饰器模式有什么区别? 控制访问 vs 增强功能 代理模式我用来做权限控制,装饰器用来做日志增强
4 策略模式和状态模式有什么区别? 行为选择 vs 状态切换 策略模式客户端决定,状态模式由内部状态自动切换
5 观察者模式在JDK中哪里用到了? 源码理解 EventListener、Swing、Spring的事件机制
6 适配器模式和桥接模式有什么区别? 接口转换 vs 抽象与实现分离 适配器是事后补救,桥接是事前设计
7 模板方法模式和策略模式怎么选? 继承 vs 组合 算法骨架固定用模板,算法可替换用策略
8 建造者模式解决了什么问题? 复杂对象构建 参数多、有必填可选、构建过程复杂时用
9 设计模式的六大原则是什么? 理论基础 重点讲开闭原则和依赖倒置,举实际重构例子
10 你在项目中用过哪些设计模式? 实战经验 准备2-3个真实案例,讲清楚“为什么用”和“效果如何”

面试小技巧:回答第10题时,不要只列模式名字。我一般会这样说:“在XX项目中,我用了策略模式来处理多种支付方式。因为支付逻辑经常变,用策略模式后,新增一种支付方式只需要加一个类,不改原有代码。”——你看,模式名、场景、好处,全说清楚了。

30.2 模式对比:别再傻傻分不清

说实话,设计模式里有些模式长得太像了。我刚学的时候也经常搞混。后来我总结了一个方法:看意图,不看结构

结构相似的,意图可能完全不同。下面这几组是我觉得最容易混淆的,我帮你理一理。

30.2.1 代理 vs 装饰器 vs 适配器

这三个模式都涉及“包装一个对象”,但目的完全不同。

  • 代理模式:控制访问。比如我不想让你直接访问真实对象,我帮你挡一道。
  • 装饰器模式:增强功能。比如你本来只能发文字,我帮你加上发图片的能力。
  • 适配器模式:接口转换。比如你的接口是USB,我的设备是Type-C,我帮你转一下。

我记得有一次面试,候选人说“代理和装饰器差不多”。我追问了一句:“那你在什么场景下会用代理,什么场景下会用装饰器?”他答不上来了。嗯,这就是没理解意图。

30.2.2 策略 vs 状态

这两个模式结构几乎一模一样——都有一个上下文,都委托给具体实现。但区别在于:

  • 策略模式:客户端主动选择策略。比如你选支付宝还是微信支付,你自己决定。
  • 状态模式:状态自动切换。比如订单状态从“待支付”变成“已支付”,是系统内部触发的。

说白了,策略模式是“我选你”,状态模式是“它变我”。

30.2.3 工厂方法 vs 抽象工厂

这个区别其实很简单:

  • 工厂方法:一个工厂生产一种产品。比如一个手机工厂只生产手机。
  • 抽象工厂:一个工厂生产一系列产品。比如一个电子工厂既生产手机,又生产耳机,还生产充电器。

抽象工厂解决的是“产品族”的问题。你想想看,如果你要生产一套智能家居设备,每个设备都有不同品牌,这时候抽象工厂就派上用场了。

30.3 如何选择设计模式?

这是最实际的问题。很多初学者会问:“我拿到一个需求,怎么知道该用哪个模式?”

我的答案是:别一开始就想模式,先想变化点

选择设计模式的黄金法则:找到系统中“会变化”的部分,然后用模式把变化封装起来。

具体怎么做?我一般分三步走:

  1. 找出变化点:哪些需求未来可能会改?哪些逻辑经常变?
  2. 确定变化类型:是算法变化?是对象创建方式变化?是行为变化?
  3. 匹配模式:根据变化类型,选择对应的模式。

举个例子。我之前做一个支付系统,一开始只支持微信支付。但我心里清楚,未来肯定会加支付宝、银行卡、甚至数字货币。这就是一个典型的变化点——支付方式会变。

变化类型是“算法/行为变化”。那匹配什么模式?策略模式。于是我把每种支付方式封装成一个策略类,客户端根据需要选择。后来加支付宝时,只加了一个类,改了一行配置代码。嗯,这种感觉很爽。

下面这张图,是我自己总结的“设计模式选择地图”。你可以把它当成一个决策树来用。

变化点是什么? 对象创建方式变化 行为/算法变化 简单工厂 工厂方法 策略模式 模板方法 对象结构/接口变化 适配器模式 桥接模式 对象间通信变化 观察者模式 中介者模式

我的经验:这张图不是万能的。实际项目中,一个场景可能同时涉及多种变化。比如既要创建对象,又要选择算法。这时候不要死套一个模式,可以组合使用。我曾经在一个项目中同时用了工厂模式和策略模式,工厂负责创建策略对象,策略负责执行算法——配合得天衣无缝。

30.4 避坑指南:设计模式常见误区

学了模式之后,很容易犯一个毛病——过度设计。我刚开始带团队时也犯过这个错。

我曾经在一个只有3个if-else的场景里硬套了策略模式。结果代码从50行变成了200行,团队其他成员看了直摇头。后来我重构回去了,只加了一个简单的Map映射。嗯,有时候最简单的方案就是最好的方案。

总结几个常见的坑:

  • 坑一:为模式而模式。代码里全是模式,但根本不需要。记住:模式是工具,不是目的。
  • 坑二:模式滥用。一个类实现了三个模式,耦合度极高。我见过有人在一个类里同时用了单例、工厂、观察者——这已经不是设计模式了,这是设计灾难。
  • 坑三:忽略业务场景。模式选对了,但业务逻辑变了,模式反而成了累赘。比如你用了单例,结果业务要求每个请求都创建新实例——单例就成了绊脚石。
  • 坑四:不重构直接上模式。我建议先写简单代码,等发现变化点后再重构引入模式。不要一开始就想着“我要用XX模式”。

30.5 如何准备设计模式面试?

最后,给你一份面试准备清单。这是我这些年总结出来的,照着做,面试基本稳了。

  1. 掌握6大原则:开闭、依赖倒置、单一职责、接口隔离、里氏替换、迪米特。面试时随口说出这些,能体现你的理论功底。
  2. 熟记5种常用模式:单例、工厂、策略、观察者、代理。这5种面试出现频率最高。
  3. 准备2-3个真实案例:每个案例说清楚“背景-问题-方案-效果”。比如:“在XX项目中,我用了观察者模式解耦了订单系统和通知系统,新增通知渠道时不需要改订单代码。”
  4. 能画图:面试时如果能画出类图或时序图,加分很多。不用太复杂,画出核心关系就行。
  5. 能对比:上面说的那几组易混淆模式,一定要能说清楚区别。

最后说一句:设计模式不是背出来的,是用出来的。你每用一次,就理解深一层。别怕用错,怕的是不用。我到现在还在不断学习,每次重构代码时,都会想“这里能不能用模式优化一下?”——这种习惯,比背下所有模式都重要。

好了,设计模式精讲到这里就结束了。希望这些内容对你有帮助。如果你在项目中遇到具体问题,欢迎随时交流。记住:模式是死的,人是活的。灵活运用,才是真本事。