软考专题 · 设计模式 GoF 23(选择题 25 + 23 种模式一句话速查 + 场景识别 + 论文提纲)
设计模式是系统架构设计师综合知识里的稳定送分题——每年 2-4 道选择题(含一类”给一段场景描述、判断该用哪个模式”的题,以及”模式归属哪一大类””易混模式辨析””SOLID 原则”),论文偶尔出”论设计模式及其应用 / 论面向对象设计原则”,案例里的 UML 建模题也可能让你识别类图对应的模式。这篇把 23 种模式一句话速查 + 易混对比 + 七大设计原则、25 道高频选择题(带 ✅ 答案 + 解析)、场景识别速查表(看到这种描述 → 选这个模式)、案例 UML 题套路、论文万能提纲打包在一起。内容来自开源仓库
PeterGuy326/senior-software-architect-review。回到 软考导览页 看完整专题清单。
一、必背:23 种模式 + 设计原则
GoF 三大类口诀 + 数量
创建 5、结构 7、行为 11——一共 23 种。
- 创建型(5)关注”对象怎么造”:工抽建原单 = 工厂方法、抽象工厂、建造者、原型、单例
- 结构型(7)关注”对象怎么拼”:适桥组装外享代 = 适配器、桥接、组合、装饰器、外观、享元、代理
- 行为型(11)关注”对象怎么协作 / 职责怎么分”:责命解迭中备观状策模访 = 责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者
创建型 5(一句话意图 + 典型场景 + 关键点)
| 模式 | 一句话意图 | 典型场景 / 例子 | 关键点 |
|---|---|---|---|
| 单例 Singleton | 保证一个类只有一个实例,并提供全局访问点 | 配置管理器、线程池、连接池、日志器、Spring Bean 默认作用域 | 关注线程安全(双重检查锁 / 静态内部类 / 枚举);饿汉式(类加载即创建,简单但可能浪费)vs 懒汉式(首次用时创建,需加锁) |
| 工厂方法 Factory Method | 定义创建对象的接口,让子类决定实例化哪个类 | 框架扩展点、插件注册、Collection.iterator() |
一个工厂对应一类产品;新增产品 = 新增一个工厂子类,符合 OCP |
| 抽象工厂 Abstract Factory | 提供创建一族相关 / 相互依赖对象的接口,无需指定具体类 | 跨平台 UI 控件族、多数据库方言(连接 + 语句 + 结果集)、换肤 | 强调产品族整体切换;新增”产品族”易,新增”产品种类”要改所有工厂(OCP 不友好) |
| 建造者 Builder | 将一个复杂对象的构建过程与它的表示分离,同样的构建过程可造不同表示 | 装配有 20+ 可选参数的对象、SQL Builder、报表 / 文档组装、StringBuilder |
链式 API 替代”伸缩构造器反模式”;Director 负责流程,Builder 负责零件 |
| 原型 Prototype | 用原型实例指定要创建对象的种类,通过克隆创建新对象 | 创建代价高的对象、大量相似对象、需要保存当前状态副本 | 注意深拷贝 vs 浅拷贝;Java Object.clone() / 序列化深拷贝 |
结构型 7(一句话意图 + 典型场景 + 关键点)
| 模式 | 一句话意图 | 典型场景 / 例子 | 关键点 |
|---|---|---|---|
| 适配器 Adapter | 把一个类的接口转换成客户期望的另一个接口,让原本不兼容的类协同工作 | 对接旧系统 / 第三方 SDK、InputStreamReader(字节流→字符流)、Spring MVC HandlerAdapter |
解决接口不兼容;分对象适配器(组合,常用)和类适配器(多继承) |
| 桥接 Bridge | 将抽象部分与它的实现部分分离,使两者可以独立变化 | “形状 × 颜色””设备 × 遥控器””消息类型 × 发送渠道”两个维度独立扩展 | 用组合代替继承,避免类的笛卡尔积爆炸;抽象类持有实现接口的引用 |
| 组合 Composite | 将对象组合成树形结构表示”部分-整体”层次,使客户对单个对象和组合对象的使用具有一致性 | 文件 / 文件夹、GUI 容器树、组织架构、菜单 | 叶子节点和容器节点实现同一接口,客户端统一处理;典型”递归组合” |
| 装饰器 Decorator | 动态地给一个对象增加额外职责,比生成子类更灵活 | Java I/O 流(BufferedInputStream/GZIPInputStream 层层包裹)、Web 过滤器叠加、奶茶加料 |
装饰器与被装饰者实现同一接口,可层层嵌套;目的是加功能而非控制访问 |
| 外观 Facade | 为子系统中的一组接口提供一个一致的高层接口,使子系统更易使用 | 一键启动 / 编译 / 下单流程封装、第三方支付聚合入口、javax.faces |
不”转换”接口(区别于适配器),而是”简化 + 统一入口”;客户端只与 Facade 打交道 |
| 享元 Flyweight | 运用共享技术有效支持大量细粒度对象的复用 | 围棋棋子、文本编辑器中的字符对象、游戏中大量相同精灵共享纹理、Integer 缓存(-128~127)、连接池 |
区分内部状态(可共享、不变)和外部状态(不共享、由客户端传入);用工厂池管理 |
| 代理 Proxy | 为另一个对象提供一个代理 / 占位符以控制对它的访问 | 远程代理(RPC)、虚拟代理(延迟加载大图)、保护代理(权限)、Spring AOP(JDK 动态代理 / CGLIB) | 代理与真实对象实现同一接口;目的是控制访问 / 增强访问(鉴权、缓存、日志、延迟),不改变功能本身 |
行为型 11(一句话意图 + 典型场景 + 关键点)
| 模式 | 一句话意图 | 典型场景 / 例子 | 关键点 |
|---|---|---|---|
| 责任链 Chain of Responsibility | 让多个对象都有机会处理请求,请求沿链传递直到有对象处理它 | Servlet Filter / 拦截器链、审批流(组长→经理→总监)、订单多级校验、Netty PipeLine、异常处理链 | 每个 Handler 持有 next 引用;可动态组装、调整顺序;解耦发送者与接收者 |
| 命令 Command | 将”请求”封装成对象,从而可用不同请求对客户进行参数化、排队、记录日志、支持撤销 | 撤销 / 重做、任务队列、事务、宏命令、GUI 按钮绑定动作 | “请求”对象化后可存储、传递、组合;Invoker—Command—Receiver 三角 |
| 解释器 Interpreter | 给定一个语言,定义它文法的一种表示,并定义一个解释器来解释语言中的句子 | 简单规则引擎、SQL / 正则 / 表达式求值、模板语言 | 文法用类层次表示(终结符 / 非终结符);适合简单且稳定的小语言,复杂语言不划算 |
| 迭代器 Iterator | 提供一种方法顺序访问一个聚合对象中的各元素,又不暴露其内部表示 | java.util.Iterator、foreach、各种集合遍历 |
把”遍历”职责从集合中剥离;游标与集合解耦 |
| 中介者 Mediator | 用一个中介对象来封装一系列对象的交互,使各对象不需显式相互引用,从而降低耦合 | 聊天室、MVC 控制器、机场塔台、复杂表单控件联动 | 把”网状多对多”调用改成”星型一对多”;中介者集中协调(注意自己别变”上帝类”) |
| 备忘录 Memento | 在不破坏封装性的前提下,捕获并外部化一个对象的内部状态,以便以后恢复 | 撤销 / 回退、游戏存档、事务回滚、编辑器快照 | Originator 创建 / 恢复备忘录,Caretaker 只保管不窥视内部 |
| 观察者 Observer | 定义对象间一对多的依赖,当一个对象状态改变时,所有依赖它的对象都得到通知并自动更新 | 事件 / 消息订阅(MQ)、Spring ApplicationEvent、MVC 模型变更刷新视图、GUI 监听器 |
Subject 维护观察者列表,状态变化时 notify;推 / 拉模型;发布-订阅是其变体 |
| 状态 State | 允许一个对象在其内部状态改变时改变它的行为,使对象看起来像修改了它的类 | 订单状态机(待付→已付→已发→已收→已评)、TCP 连接状态、工作流引擎 | 每个状态一个类,状态切换由状态对象内部驱动;消除大量 if/switch (state) |
| 策略 Strategy | 定义一系列算法,把它们一个个封装起来,并使它们可互相替换 | 多种支付 / 计费 / 风控 / 排序 / 压缩 / 折扣算法运行时切换、Spring 的 Resource 加载 |
客户端外部选择算法;典型用来消灭 if/else (type);符合 OCP |
| 模板方法 Template Method | 定义一个算法的骨架,将某些步骤延迟到子类中实现,使子类可在不改变结构的情况下重定义某些步骤 | JdbcTemplate / RestTemplate、HttpServlet.service()、各类”流程框架 + 钩子” |
父类定义流程(常是 final),子类只填空;含钩子方法(hook);体现”好莱坞原则——别调用我,我会调用你” |
| 访问者 Visitor | 表示一个作用于某对象结构中各元素的操作,使你可以在不改变各元素类的前提下定义作用于这些元素的新操作 | 编译器 AST 遍历(类型检查 / 代码生成 / 优化各是一个 Visitor)、报表 / 导出多格式、对象结构上的多种分析 | 把”操作”从”元素”中抽出来;双重分派(element.accept(visitor) → visitor.visit(element));元素类稳定、操作经常加 → 适合,反之不适合 |
易混淆模式对比(高频辨析点)
| 对比 | 核心差异(一句话) |
|---|---|
| 工厂方法 vs 抽象工厂 | 工厂方法造一种产品(一个工厂一个产品);抽象工厂造一族相关产品(一个工厂多个产品、整体切换) |
| 适配器 vs 装饰器 vs 代理 | 三者都”包了一层、实现同一接口”,但目的不同:适配器=改接口让不兼容能用;装饰器=加功能、可层层叠加;代理=控制访问(鉴权 / 延迟 / 远程 / 缓存),不增减功能 |
| 策略 vs 状态 | 都是”一族类换着用”。策略:算法互不感知,由客户端外部选;状态:状态彼此知道下一个状态,切换由状态对象内部驱动(订单自己从”待付”流转到”已付”) |
| 策略 vs 模板方法 | 策略用组合 + 委托整体替换算法;模板方法用继承、父类定骨架、子类只改个别步骤。策略换”整个算法”,模板方法换”算法里某几步” |
| 桥接 vs 适配器 | 桥接是设计前期有意拆出”抽象 / 实现”两个维度让其独立演化;适配器是事后补救,让已有的、接口不匹配的类能协作 |
| 组合 vs 装饰器 | 类图很像(都递归持有同接口对象),但意图不同:组合表达”部分-整体“树形层次、统一处理叶子和容器;装饰器是”给一个对象套层皮加职责“,结构上是一条链而非一棵树 |
| 外观 vs 适配器 | 外观给子系统一个新的、简化的高层入口(封装一组接口);适配器是转换一个已有接口成另一个客户期望的接口 |
| 代理 vs 装饰器 | 代理通常自己控制真实对象的生命周期 / 是否真的去调(延迟、缓存、拒绝);装饰器拿到的是外部传入的对象、目的是透明地增强功能 |
七大面向对象设计原则(SOLID + 2)
| 原则 | 一句话 |
|---|---|
| SRP 单一职责 | 一个类只应有一个引起它变化的原因(职责单一、高内聚) |
| OCP 开闭原则 ⭐核心 | 对扩展开放、对修改关闭——加新功能靠新增代码(继承 / 实现接口 / 配置),而不是改老代码 |
| LSP 里氏替换 | 子类对象能无缝替换父类对象而不破坏程序正确性(子类不要削弱前置、不要增强后置、不要抛父类没声明的异常) |
| ISP 接口隔离 | 客户不应被迫依赖它用不到的方法——多个专用小接口 胜过一个臃肿的胖接口 |
| DIP 依赖倒置 | 高层模块不依赖低层模块,两者都依赖抽象;抽象不依赖细节,细节依赖抽象(Spring 依赖注入的理论基础) |
| 迪米特法则 LoD(= 最少知识原则 LKP) | 一个对象应对其他对象保持最少了解,只和”直接朋友”通信(少出现 a.getB().getC().doSth()) |
| 合成 / 聚合复用原则 CRP | 优先用组合 / 聚合,而不是继承来达到复用目的(继承破坏封装、耦合强;组合更灵活) |
一句话记忆:OCP 是目标,其余原则是手段;几乎所有 GoF 模式本质都是”为了在某个变化点上满足 OCP”。
区分:GoF 设计模式 ≠ 架构模式 ≠ 企业应用模式(考试常混)
| 层次 | 例子 | 解决什么 |
|---|---|---|
| GoF 设计模式(类 / 对象级) | 23 种:单例、策略、观察者、代理…… | 类与对象之间的协作结构 |
| 架构(风格)模式(系统级) | 分层、MVC / MVVM / MVP、管道-过滤器、微内核(插件)、事件驱动 / 发布订阅、客户端-服务器、SOA / 微服务、CQRS、事件溯源、Sidecar、BFF | 整个系统的宏观骨架与组件划分 |
| 企业应用 / J2EE 模式(中间层) | DAO、DTO、Service Locator、Front Controller、值对象、仓储 Repository、工作单元 | 分层架构中某一层的典型实现套路 |
注意:MVC 是架构模式,不是 GoF 模式;单例 / 策略是 GoF 模式,不是架构模式——选择题经常把它们混在一组让你挑”哪个不属于……”。
二、高频选择题(25 题,✅ 为正确选项)
1. GoF 设计模式按目的可分为三大类,不包括:
A. 创建型 B. 结构型 C. 行为型 ✅ D. 集成型
GoF 23 种按目的分为创建型(5)、结构型(7)、行为型(11);按范围还可分类级 / 对象级。
2. 下列模式全部属于创建型的是:
A. 单例、适配器、原型 B. 工厂方法、观察者、建造者 ✅ C. 单例、工厂方法、抽象工厂、建造者、原型 D. 抽象工厂、装饰器、责任链
创建型 5 个口诀:”工抽建原单”。
3. 下列模式属于结构型的是:
A. 备忘录 B. 访问者 ✅ C. 代理 D. 状态
结构型 7 个:”适桥组装外享代”——适配器、桥接、组合、装饰器、外观、享元、代理。
4. 下列模式属于行为型的是:
A. 桥接 B. 享元 ✅ C. 模板方法 D. 原型
行为型 11 个:”责命解迭中备观状策模访”。
5. 某电商系统支持微信、支付宝、银联、数字人民币多种支付方式,要求运行时可由用户动态选择并互相替换,新增渠道不改调用方代码。最适合的模式是:
A. 工厂方法 ✅ B. 策略 C. 观察者 D. 装饰器
策略模式封装可互换的算法族、由客户端外部选择,新增策略类即可,符合 OCP。这是最典型的”看场景选模式”题。
6. 订单提交时需依次执行”库存校验 → 价格校验 → 风控校验 → 用户状态校验”,且各校验步骤的顺序和组合可灵活配置。最适合的模式是:
A. 策略 ✅ B. 责任链 C. 命令 D. 状态
责任链:每个处理器判断是否处理、不处理则交给下一个,可动态组装链条、调整顺序;典型还有 Servlet Filter、审批流。
7. 某消息系统中,一条消息发布后需要自动通知所有已订阅的下游模块(履约、对账、推送)。最适合的模式是:
A. 责任链 ✅ B. 观察者 C. 中介者 D. 命令
观察者定义一对多依赖,主题状态变化时自动通知全部观察者;Spring 的
ApplicationEvent、MQ 的发布-订阅都是其体现。
8. 需要把一个已有的、接口不兼容的第三方类库接入到现有系统,使其能像现有接口那样被调用。应选用:
A. 装饰器 ✅ B. 适配器 C. 外观 D. 代理
适配器解决”接口不兼容”——把一个类的接口转换成客户期望的另一个接口。
9. 要为一个由数十个子系统组成的复杂模块提供一个统一的、简化的高层入口,让客户端不必了解内部细节。应选用:
A. 适配器 B. 代理 ✅ C. 外观 D. 中介者
外观(Facade)为子系统提供一致的高层接口,降低使用复杂度;它”简化入口”而非”转换接口”。
10. Spring AOP 在运行期为目标对象生成增强对象、拦截方法调用以织入横切逻辑(事务、日志、权限),其底层实现属于:
A. 装饰器 ✅ B. 代理 C. 适配器 D. 模板方法
Spring AOP 使用 JDK 动态代理(基于接口)或 CGLIB(基于子类)实现方法拦截——代理模式”控制 / 增强对该对象的访问”。
11. Java I/O 中 new BufferedInputStream(new GZIPInputStream(new FileInputStream(...))) 这种”层层包裹、动态叠加缓冲 / 解压等职责”的设计采用的模式是:
A. 适配器 ✅ B. 装饰器 C. 代理 D. 桥接
装饰器:装饰者与被装饰者实现同一接口,可层层嵌套,动态给对象增加职责,比继承更灵活。
12. 装饰器(Decorator)与代理(Proxy)的主要区别在于:
A. 装饰器在编译期确定,代理在运行期 ✅ B. 装饰器侧重”动态增加职责”,代理侧重”控制对对象的访问” C. 装饰器只能装饰一次 D. 代理不能实现接口
二者类图相似(都包一层、实现同一接口),但意图不同:加功能 vs 控制访问。
13. 状态模式(State)与策略模式(Strategy)的主要区别在于:
A. 二者没有区别 ✅ B. 状态模式中状态彼此知道下一个状态、切换由状态对象内部驱动;策略模式中算法互不感知、由客户端外部选择 C. 策略模式不能封装多个算法 D. 状态模式不可扩展
经典辨析:订单”待付→已付”的流转是状态自己驱动的(State);支付方式由用户选的是 Strategy。
14. 在不修改一组元素类的前提下,希望能够不断为这些元素新增不同的操作(如对 AST 做类型检查、代码生成、优化),最适合的模式是:
A. 迭代器 B. 组合 ✅ C. 访问者 D. 模板方法
访问者把”操作”从”元素”中抽离,用双重分派;适用于元素类稳定、操作经常增加的场景。
15. 父类中定义”连接资源 → 执行 → 释放资源”的固定流程骨架,把”执行”这一步留给子类实现(如 Spring JdbcTemplate)。这采用的是:
A. 策略 B. 工厂方法 ✅ C. 模板方法 D. 命令
模板方法在父类定义算法骨架、把可变步骤延迟到子类,常配钩子方法,体现”好莱坞原则”。
16. 构造一个拥有 20 多个可选参数、且参数组合多变的复杂配置对象,避免”伸缩构造器反模式”,最适合:
A. 原型 B. 抽象工厂 ✅ C. 建造者 D. 享元
建造者把复杂对象的”构建过程”与”表示”分离,常用链式 API 分步装配。
17. 文本编辑器中要表示成千上万个字符对象,希望通过共享相同字符(字体、字号等内部状态)来大幅降低内存占用,最适合:
A. 组合 B. 原型 ✅ C. 享元 D. 代理
享元用共享技术支持大量细粒度对象;区分内部状态(可共享)和外部状态(由客户端传入),用工厂池管理。
18. 要把”文件”和”文件夹”组织成树形结构,并希望客户端能统一处理单个文件和文件夹(如递归计算大小),最适合:
A. 装饰器 B. 桥接 ✅ C. 组合 D. 迭代器
组合模式让叶子节点(文件)和容器节点(文件夹)实现同一接口,表示”部分-整体”层次。
19. 当”消息类型(文本 / 富文本 / 视频)”和”发送渠道(短信 / 邮件 / App 推送)”两个维度都需要独立扩展、避免类的笛卡尔积爆炸时,应选用:
A. 适配器 ✅ B. 桥接 C. 装饰器 D. 抽象工厂
桥接将抽象(消息类型)与实现(发送渠道)分离,用组合代替继承,使两个维度各自独立变化。
20. 关于单例模式的实现,下列说法错误的是:
A. 饿汉式在类加载时即创建实例,线程安全但可能造成资源浪费 B. 懒汉式延迟到首次使用时创建,需要考虑多线程安全 C. 双重检查锁(DCL)需要配合 volatile 防止指令重排序 ✅ D. 静态内部类方式无法保证线程安全,必须额外加锁
静态内部类(Holder)方式利用类加载机制天然线程安全,且实现了懒加载,无需额外加锁;枚举方式还能防反射 / 反序列化破坏。
21. 下列做法中**违反开闭原则(OCP)**的是:
A. 新增折扣规则时新增一个策略实现类 B. 用装饰器动态给订单叠加优惠 ✅ C. 每新增一种支付方式就在 PaymentService 里加一个 if (type == ...) 分支并改原方法 D. 通过 SPI 机制注册新插件
OCP 要求对扩展开放、对修改关闭;不断修改核心类的条件分支正是典型违反。
22. 下列关于**里氏替换原则(LSP)**的描述,正确的是:
A. 子类不能添加父类没有的方法 ✅ B. 凡是父类对象能出现的地方,子类对象都应能替换它而不破坏程序正确性 C. 父类应当依赖子类 D. 继承层级不得超过三层
LSP 是”继承正确性”的判据:子类不要削弱前置条件、不要增强后置条件、不要抛父类未声明的异常、不要违反父类不变式。
23. “高层模块不应依赖低层模块,二者都应依赖抽象;抽象不应依赖细节,细节应依赖抽象”描述的是:
A. 单一职责原则 B. 接口隔离原则 ✅ C. 依赖倒置原则 D. 迪米特法则
依赖倒置原则(DIP)是 Spring 依赖注入 / 控制反转的理论基础;与”面向接口编程”相呼应。
24. 迪米特法则(Law of Demeter)又称:
A. 开闭原则 ✅ B. 最少知识原则(Least Knowledge Principle) C. 单一职责原则 D. 合成复用原则
一个对象应对其他对象保持最少了解,只与”直接朋友”通信,减少
a.getB().getC().doSomething()这类链式调用。
25. 下列选项中,不属于 GoF 设计模式(而是架构 / 架构风格模式)的是:
A. 单例 B. 策略 C. 观察者 ✅ D. MVC
MVC(以及 MVVM、分层、管道-过滤器、微内核、CQRS、事件溯源、微服务 Sidecar / BFF)属于架构级模式,比 GoF 高一层;GoF 23 种是类 / 对象级模式。
原文 + 解析:
exam-bank/13-design-patterns.md;本文新增题为基于公开考点的自主命题改编,避免版权风险。
三、场景识别速查表(看到这种描述 → 选这个模式)
考试里”看场景选模式”题,几乎都能在下面这张表里命中关键词。先抓题干里的”动词 / 名词信号”,再对位模式:
| 题干会怎么描述(关键信号) | 选这个模式 | 所属大类 |
|---|---|---|
“封装一系列算法,使它们可互相替换“/ 多种支付 / 计费 / 风控 / 排序方式运行时切换 / 消灭一堆 if (type) |
策略 Strategy | 行为型 |
| “一个请求沿着链传递,直到被某个对象处理”/ 多级审批 / 过滤器链 / 拦截器链 | 责任链 Chain of Responsibility | 行为型 |
| “对象状态改变时自动通知所有依赖者“/ 事件订阅 / 发布-订阅 / 监听器 / MQ 通知 | 观察者 Observer | 行为型 |
| “动态地给对象增加职责 / 功能,且不修改原有类,可层层叠加”/ I/O 流包裹 / 加料 / 功能增强链 | 装饰器 Decorator | 结构型 |
| “控制对另一个对象的访问“/ 延迟加载 / 远程访问(RPC)/ 权限保护 / 缓存 / AOP | 代理 Proxy | 结构型 |
| “让接口不兼容的(已有 / 第三方)类能协同工作“/ 旧系统对接 / 适配第三方 SDK | 适配器 Adapter | 结构型 |
| “为复杂子系统提供一个统一的高层接口 / 简化入口“ | 外观 Facade | 结构型 |
| “运用共享技术支持大量细粒度对象”/ 区分内部状态与外部状态 / 字符池 / 棋子 / 连接池 | 享元 Flyweight | 结构型 |
| “将抽象与实现分离,使二者可独立变化“/ 两个维度各自扩展、避免类爆炸 | 桥接 Bridge | 结构型 |
| “将对象组合成树形结构表示部分-整体层次,统一处理叶子和容器“/ 文件系统 / 菜单树 / 组织架构 | 组合 Composite | 结构型 |
“定义算法的骨架,把某些步骤延迟到子类“/ 流程固定、个别步骤可变 / 钩子方法 / XxxTemplate |
模板方法 Template Method | 行为型 |
| “在不修改元素类的前提下,定义作用于这些元素的新操作“/ AST 多种遍历 / 报表多格式导出 | 访问者 Visitor | 行为型 |
| “对象内部状态改变时改变其行为“/ 订单 / 工单 / TCP 状态机 / 状态自己驱动流转 | 状态 State | 行为型 |
| “将请求封装成对象“/ 支持撤销重做 / 任务排队 / 宏命令 / 操作日志 | 命令 Command | 行为型 |
| “顺序访问聚合对象元素,又不暴露内部结构“/ 集合遍历 / 游标 | 迭代器 Iterator | 行为型 |
| “用一个中介对象封装一系列对象的交互,把网状调用变星型“/ 聊天室 / 控制器 / 控件联动 | 中介者 Mediator | 行为型 |
| “捕获并保存对象内部状态,以便以后恢复“/ 撤销 / 存档 / 快照 / 事务回滚 | 备忘录 Memento | 行为型 |
| “为一种小语言 / 表达式 / 规则定义文法表示并解释执行“ | 解释器 Interpreter | 行为型 |
| “保证一个类只有一个实例并提供全局访问点“/ 配置 / 线程池 / 日志器 | 单例 Singleton | 创建型 |
| “由子类决定实例化哪个类“/ 一个工厂一种产品 / 框架扩展点 / 插件 | 工厂方法 Factory Method | 创建型 |
| “创建一族相关 / 相互依赖的对象,无需指定具体类”/ 跨平台 UI 控件族 / 多数据库方言 / 换肤 | 抽象工厂 Abstract Factory | 创建型 |
| “分步构造一个复杂对象,构建过程与表示分离”/ 20+ 可选参数 / 链式 API / 报表组装 | 建造者 Builder | 创建型 |
| “通过克隆已有对象来创建新对象”/ 创建代价高 / 大量相似对象 / 保存状态副本 | 原型 Prototype | 创建型 |
| “新增功能只需扩展、不改原代码“ | 开闭原则 OCP(不是模式,是原则) | 设计原则 |
| “依赖抽象而非具体实现”/ 控制反转 / 依赖注入 | 依赖倒置原则 DIP | 设计原则 |
| “优先组合而非继承“ | 合成复用原则 CRP | 设计原则 |
速查原表见
cheatsheets/design-patterns-gof23.md,脑图见mind-maps/design-patterns.md。
四、案例 / UML 题里怎么用 + 论文里怎么用
案例 UML 建模题:识别 / 补全模式的套路
UML 建模案例题(25 分)有时会给一段需求 + 一张半成品类图,让你识别它对应哪个 GoF 模式、补全缺失的类 / 接口 / 关联、并填空模式中的角色。套路是三步:
- 看类图结构特征 → 报模式名:
- 有”抽象类持有一个
next/successor自引用” → 责任链; - 有”抽象组件 + 叶子 + 容器(容器又递归持有组件列表)” → 组合;
- 有”装饰抽象类继承组件、又持有一个组件引用、且可嵌套” → 装饰器;
- 有”Context 持有一个 Strategy 接口、多个具体策略实现它” → 策略;
- 有”Subject 持有 Observer 列表、
attach/detach/notify“ → 观察者; - 有”抽象类里一个
final模板方法 + 若干abstract步骤方法” → 模板方法; - 有”Proxy 与 RealSubject 实现同一接口、Proxy 内部引用 RealSubject” → 代理;
- 有”AbstractFactory 接口 + 若干
createXxx()方法 + 多个具体工厂” → 抽象工厂。
- 有”抽象类持有一个
- 说意图:一句”该模式意图是……(套定义)”。
- 做角色映射:把题干里的具体类对到模式角色上,如”
OrderValidator对应抽象处理者 Handler,InventoryValidator/RiskValidator对应具体处理者 ConcreteHandler,Order对应请求 Request”。
高分句举例:
- “该类图中
AbstractFilter持有指向自身类型的nextFilter引用,子类各自实现doFilter并决定是否调用nextFilter.doFilter——这是责任链模式,意图是让多个对象都有机会处理请求、解耦请求发送者与接收者;缺失的关联是AbstractFilter到AbstractFilter的自聚合(next)。” - “
PaymentContext通过组合方式持有PaymentStrategy接口、运行时由setStrategy注入具体策略——这是策略模式,符合开闭原则:新增DigitalRMBPayment只需实现接口、不改PaymentContext。” - “
FileSystemNode为抽象组件,File为叶子、Directory既是组件又聚合List<FileSystemNode>——这是组合模式,使客户端能用getSize()统一处理文件与目录(递归)。”
五、论文万能提纲(约 2500 字)
典型题目:论软件设计模式及其应用 / 论设计模式在软件开发(架构)中的应用 / 论面向对象的设计原则与模式 / 论面向对象设计原则与重构的应用。
⚠️ 自主命题改编,建议严格 120 分钟限时写完整 2500 字,再对照提纲与评分维度复盘。完整理论 + 2 道模拟论文题(含提纲式参考答案、加分关键词、评分维度、避坑)见
paper-topics/10-design-patterns.md。
4 段式提纲
1 | 1. 项目背景(约 350 字) |
摘要模板(约 300 字)
“我于 2023 年主导了 {电商订单核心 / 支付清结算 / 在线教育} 系统的设计与重构,担任 {核心架构师}。系统涉及 {15 种支付方式 / 8 类营销规则 / 30 种风控策略},原代码 if-else 嵌套深、新增一个渠道平均改 8 个文件、单元测试覆盖率仅 30%。本文以该项目为背景,论述设计模式的系统化应用:用策略模式做支付 / 风控规则可插拔、工厂方法 + 抽象工厂做多数据源对象创建、观察者模式做订单事件通知、责任链做可配置校验链、装饰器做优惠叠加、模板方法做批处理流程骨架、单例 + 代理做资源管理与远程调用增强,并辅以 CQRS、事件溯源等架构级模式;同时落地 OCP / DIP / SRP / ISP 等设计原则。最终新增支付方式从 3 天降至 0.5 天、扩展成本下降约 70%、单元测试覆盖率提升至 85%、缺陷率下降 60%。实践表明:模式的价值在于守护”变化点上的可修改性”,但需控制数量、避免过度设计。”
加分关键词清单
| 类别 | 必写术语 |
|---|---|
| 理论术语 | GoF、创建型 / 结构型 / 行为型、SOLID(SRP / OCP / LSP / ISP / DIP)、迪米特法则、合成复用原则、限界上下文、CQRS、事件溯源、Saga、Sidecar、BFF |
| 模式 / 方法论 | 策略、工厂方法 / 抽象工厂、观察者、责任链、装饰器、模板方法、单例、代理、状态机、命令、Spring DI、SPI、依赖注入 / 控制反转 |
| 量化范围 | 模式 5~8 种 + 2 种架构级 / 扩展成本 -70% / 接入 3d→0.5d / 覆盖率 30%→85% / 缺陷率 -60% / 团队 18 人 |
| 业界对标点缀 | Spring Framework(代理 / 模板方法 / 工厂)、Netflix Hystrix(断路器)、阿里 SOFA、Axon Framework(事件溯源)、Camunda(Saga / 工作流) |
避坑提醒
- ❌ 把 23 种模式从头罗列一遍 → ✅ 只选 5~8 种深入讲,每种含”场景 + 目的 + 类设计 + 权衡 + 量化收益”
- ❌ 模式名乱贴(明明是个 if 也说成”策略模式”)→ ✅ 必须”场景 + 目的 + 具体类设计”对得上
- ❌ 全篇只有 GoF → ✅ 点缀架构级模式(CQRS / 事件溯源 / Sidecar / BFF),体现层次
- ❌ 不讲权衡 → ✅ 每种模式都写”为什么选它而不是 XX”,并专门一段讲”模式滥用 → 类爆炸 / 可读性下降 → 适度使用”
- ❌ 为用模式而用模式 → ✅ 只在”真实变化点”上引入模式,简单稳定的地方不必套用——这是评委最在意的成熟度信号
软考专题系列第 9 篇。同系列:架构评估 ATAM · 架构风格对比 · 微服务与云原生 · 数据库设计 · 消息中间件与缓存 · 法律法规与标准化 · 计算题专项 · 软件架构安全。完整清单见 软考导览页。发现题目错误欢迎到 仓库 开 issue。






