导图社区 23种经典设计模式
23种经典设计模式,按照创建型、结构型、行为型、创建型、结构型几大类进行了系统梳理,每种模式都有具体内容关联,有助于读者快速掌握设计模式。
编辑于2025-10-12 18:25:1323种经典设计模式,按照创建型、结构型、行为型、创建型、结构型几大类进行了系统梳理,每种模式都有具体内容关联,有助于读者快速掌握设计模式。
大模型微调与对齐技术(SFT DPO RLHF LoRA),涵盖核心目标、参数高效微调技术(PEFT)、微调与对齐方法、方法对比、LLaMA Factory实战要点、应用场景建议以及面试/简历关键词等方面,适合用于技术研究、项目实践以及求职准备等场景。
随机过程在数学、科学和工程中有着越来越广泛的应用。本书包括随机过程一些基本而又重要的内容:条件期望,Markov链,Poisson过程和Brown运动;同时也包括Ito积分和随机微分方程等应用范围越来越广的内容。
社区模板帮助中心,点此进入>>
23种经典设计模式,按照创建型、结构型、行为型、创建型、结构型几大类进行了系统梳理,每种模式都有具体内容关联,有助于读者快速掌握设计模式。
大模型微调与对齐技术(SFT DPO RLHF LoRA),涵盖核心目标、参数高效微调技术(PEFT)、微调与对齐方法、方法对比、LLaMA Factory实战要点、应用场景建议以及面试/简历关键词等方面,适合用于技术研究、项目实践以及求职准备等场景。
随机过程在数学、科学和工程中有着越来越广泛的应用。本书包括随机过程一些基本而又重要的内容:条件期望,Markov链,Poisson过程和Brown运动;同时也包括Ito积分和随机微分方程等应用范围越来越广的内容。
📚 23 种设计模式分类回顾:
| 类别 | 包含模式(部分) |
| ----------- | ----------------------------------------- |
| 创建型(5)
| 单例、工厂方法、抽象工厂、建造者、原型 |
| 结构型(7)
| 适配器、桥接、组合、装饰、外观(门面)、享元、代理 |
| 行为型(11)
| 策略、观察者、命令、状态、责任链、中介者、迭代器、访问者、备忘录、解释器、模板方法 |
创建型设计模式
单例
工厂方法
抽象工厂
建造者模式 (Builder Pattern)
用来“分步骤、按顺序
把一堆零件组装成复杂对象”,避免构造函数参数爆炸
。
解决了:构造参数过多,参数组合爆炸,对象不可变的痛点
2. 使用场景
| 痛点 | 例子 |
| ------ | ------------------------------------------------- |
| 构造参数过多 | Pizza(size, cheese, pepperoni, bacon, …)
10 个参数 |
| 参数组合爆炸 | 构造器/工厂难以表达 可选配料
|
| 对象不可变 | 需要 一次性
构建好再使用 |
────────────────────
3. 经典结构(类图一句话)Director → Builder → ProductDirector
:指挥组装的顺序(可省略,由客户端自己链式调用)。Builder
:定义 “造零件”接口(buildSize()、buildCheese() …)。ConcreteBuilder
:真正造零件,内部持有半成品对象。Product
:最终复杂对象。
4. 最简代码(链式 / 流式写法,JDK 8 直接可用)
public class Computer {
private final String cpu;
private final int ram;
private final boolean ssd;
private Computer(Builder b) {
this.cpu = b.cpu;
this.ram = b.ram;
this.ssd = b.ssd;
}
public static class Builder {
private String cpu;
private int ram;
private boolean ssd;
public Builder cpu(String cpu) { this.cpu = cpu; return this; }
public Builder ram(int ram) { this.ram = ram; return this; }
public Builder ssd(boolean ssd) { this.ssd = ssd; return this; }
public Computer build() { return new Computer(this); }
}
}
// 用法
Computer pc = new Computer.Builder()
.cpu("i9")
.ram(32)
.ssd(true)
.build();
──────────────────── 5. 变种 & 实战
表格
复制
|形式|场景|
|:--|:--|
|链式 Builder
|Lombok @Builder
、AutoValue、Immutables|
|静态内部类 Builder
|JDK StringBuilder
、Spring Security OAuth2ClientBuilder
|
|流式 DSL
|MyBatis SqlSessionFactoryBuilder
|
|生成器框架
|Lombok 注解、Maven/Gradle 插件|
────────────────────
6. 与其他创建型模式对比
|维度|Builder|Factory Method|Abstract Factory|
|:--|:--|:--|:--|
|目的|复杂对象 分步
构建|创建 一类
对象|创建 一族
对象|
|粒度|可选零件
|整体替换
|整套零件
|
────────────────────
一句话总结建造者模式 = “把 10 个参数的构造函数拆成 10 个链式方法”,让复杂对象的创建既安全又优雅,属于创建型模式中的“组装专家”。
结构型设计模式
门面模式(Facade Pattern)
什么是门面模式?(门面模式的概念)门面模式(Facade Pattern)是 23 种经典设计模式之一
。门面模式(Facade Pattern)是一种结构型设计模式,它的核心思想是:为一个复杂子系统提供一个统一、简化的高层接口,让客户端无需了解子系统内部的复杂实现,也能方便、安全地使用它的功能。
🧱 举个生活中的例子:
想象你在家看电影:
没有门面:你需要手动打开投影仪 → 放下幕布 → 打开音响 → 选择片源 → 调灯光 → 播放
有了门面:你只需按一个按钮 “开始观影”,所有步骤自动完成
这个“开始观影”按钮,就是 门面(Facade)
💡 代码结构示例(Java 风格):
// 复杂的子系统类
class Projector {
void on() { System.out.println("投影仪开启"); }
void off() { System.out.println("投影仪关闭"); }
}
class SoundSystem {
void on() { System.out.println("音响开启"); }
void setVolume(int v) { System.out.println("音量设为 " + v); }
}
class Lights {
void dim() { System.out.println("灯光调暗"); }
}
// 门面类 —— 提供简单接口
class HomeTheaterFacade {
private Projector projector;
private SoundSystem sound;
private Lights lights;
public HomeTheaterFacade(Projector p, SoundSystem s, Lights l) {
this.projector = p;
this.sound = s;
this.lights = l;
}
// 高层接口:一键观影
public void watchMovie() {
lights.dim();
projector.on();
sound.on();
sound.setVolume(15);
System.out.println("准备就绪,电影开始播放!");
}
// 一键关闭
public void endMovie() {
projector.off();
sound.off();
System.out.println("电影结束,关闭设备。");
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
HomeTheaterFacade homeTheater = new HomeTheaterFacade(
new Projector(), new SoundSystem(), new Lights()
);
homeTheater.watchMovie(); // 只需调用一个方法
}
}
✅ 门面模式的优点:
| 优点 | 说明 |
|------|------|
| 简化接口
| 客户端无需了解复杂的子系统 |
| 降低耦合
| 客户端只依赖门面,不直接依赖多个子系统 |
| 提高可维护性
| 子系统变化时,只需修改门面,不影响客户端 |
| 分层设计
| 常用于系统分层(如 Controller 就是 Service 的门面) |
✅ “门面”就是“结构型”中的 外观模式(Facade)
,也译作“门面模式”。
⚠️ 注意事项:
门面模式 不阻止 客户端直接访问子系统,只是提供一个更简单的选择。
它不是“屏蔽”子系统,而是“封装复杂性”。
✅ 总结:是的,门面模式(Facade Pattern)是 23 种 GoF(Gang of Four)设计模式之一
,属于结构型模式,用于为复杂系统提供简单接口
,是解耦与分层的常用手段。
在实际开发中,如 Spring 框架中的 JdbcTemplate
、RestTemplate
,其实都体现了门面思想。
行为型(11)设计模式
策略模式(Strategy Pattern)核心思想
:定义一系列算法
,将每个算法封装起来
,并使它们可以互相替换
。算法的变化独立于使用它的客户端
。
🎯 主要组成部分:抽象策略(Strategy)
:定义一个公共接口,所有具体策略类实现这个接口。具体策略(Concrete Strategy)
:实现具体算法的类。上下文(Context)
:持有一个策略对象的引用,用于调用策略执行算法。
💡 举个简单例子:
假设你有一个排序功能,可以根据不同需求使用冒泡排序、快速排序或归并排序:
每种排序算法都实现 SortStrategy 接口。Context
类持有 setStrategy,运行时可以动态切换算法。
客户端无需修改代码,只需传入不同的策略即可改变行为。
context.setStrategy(new QuickSort());
context.sort(); // 使用快速排序
context.setStrategy(new BubbleSort());
context.sort(); // 使用冒泡排序
✅ 优点:
避免多重 if-else 或 switch 条件判断。
符合开闭原则:新增策略无需修改原有代码。
算法可自由切换,易于扩展和维护。
❌ 缺点:
策略类增多可能导致类膨胀(可通过工厂模式+反射优化)。
客户端需要知道有哪些策略可用。
🔗 常见应用场景:
支付方式选择(微信、支付宝、银联)
物流配送策略
折扣计算(满减、打折、秒杀)
排序或搜索算法切换
模板方法模式(Template Method Pattern)
**在父类中定义 操作的算法骨架(模板),把易变步骤延迟到子类中实现。模板方法使得子类可以不改变算法结构即可重定义算法的某些特定步骤。既统一流程,又允许个性化扩展
模板方法模式通常包含以下角色:
|角色|说明|
|---|---|
|AbstractClass(抽象类)
|定义算法骨架(模板方法),并声明或实现部分步骤。其中某些步骤是抽象方法或钩子方法,由子类实现。|
|ConcreteClass(具体子类)
|实现抽象类中定义的抽象方法或钩子方法,完成算法中特定步骤的具体逻辑。|
|Template Method(模板方法)
|在抽象类中定义,是一个final 方法
(防止被重写),按固定顺序调用基本方法,构成完整算法流程。|
|Primitive Methods(基本方法)
|包括:
<br>
1. 抽象方法
:必须由子类实现
<br>
2. 具体方法
:已在父类实现
<br>
3. 钩子方法(Hook Method)
:空实现或默认实现,子类可选择覆盖|
✅ 总结一句话:模板方法模式 = 父类定流程 + 子类填细节 + 钩子控分支
它是一种基于继承的算法复用机制
,在框架、中间件、基础组件中应用广泛,是面向对象设计中“封装变化”思想的经典体现。
💡 四、核心思想封装不变部分,扩展可变部分
:算法结构是稳定的,具体实现是变化的。控制反转(好莱坞原则)
:“别调用我们,我们会调用你” —— 父类控制流程,子类提供实现。代码复用 + 扩展灵活
:避免重复代码,子类只需关注自己关心的步骤。
🧪 五、代码示例(Java)
🎯 六、钩子方法(Hook Method)的作用
钩子方法是模板方法模式中非常灵活的设计:提供“可选扩展点”
,子类可以覆盖,也可以不覆盖。控制流程走向
,如上面例子中决定是否执行 addCondiments()。
默认提供空实现或合理默认值,保证父类模板方法正常运行。
✅ 七、优点封装不变逻辑,提高复用性
:算法结构写一次,多个子类共享。便于维护和扩展
:新增子类不影响主流程。符合开闭原则
:对扩展开放(加子类),对修改封闭(不改模板方法)。反向控制结构
:父类主导流程,子类提供实现,符合“好莱坞原则”。
⚠️ 八、缺点类数量可能膨胀
:每一个变体都需要一个子类。父类变更影响子类
:如果模板方法结构变化,所有子类都可能受影响。过度设计风险
:如果算法没有复用价值或变化点少,使用模板方法反而增加复杂度。
🌐 九、应用场景框架设计
:框架提供骨架,开发者填充细节(如 Spring、JUnit、Servlet)。多步骤固定流程
:
游戏角色初始化流程
数据库事务处理(开启 → 执行 → 提交/回滚)
文档处理(打开 → 解析 → 渲染 → 关闭)生命周期管理
:Activity/Fragment 的 onCreate()、onStart()、onResume() 等。测试框架
:JUnit 中的 setUp() → testXXX() → tearDown()。
🆚 十、与其他模式对比
|模式|与模板方法的区别|
|---|---|
|策略模式
|用组合代替继承,算法可动态替换;模板方法用继承,算法结构固定。|
|工厂方法
|是模板方法的一种特例,模板方法更通用。|
|建造者模式
|用于构造复杂对象,步骤可调整顺序;模板方法强调固定顺序。|
📦 十一、在 JDK 和框架中的应用
1. Java —— java.util.AbstractList
java
浅色版本
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
// 模板方法
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
// 子类如 ArrayList 重写以提供具体实现
}
2. Servlet —— HttpServlet
java
浅色版本
protected void service(HttpServletRequest req, HttpServletResponse resp) {
// 模板方法:根据 method 调用 doGet/doPost 等
String method = req.getMethod();
if (method.equals("GET")) {
doGet(req, resp);
} else if (method.equals("POST")) {
doPost(req, resp);
}
// ...
}
// 子类只需重写 doGet/doPost,无需关心 service 流程
3. JUnit 3/4 —— TestCase
java
浅色版本
public void runBare() {
setUp(); // 钩子/抽象
runTest(); // 执行测试方法
tearDown(); // 钩子/抽象
}
✍️ 十二、设计建议
模板方法应声明为 final,防止被子类篡改流程。
抽象方法命名应清晰表达意图(如 doExecute(), fetchData())。
合理使用钩子方法提供扩展点,但不要滥用。
如果子类仅需实现1~2个方法,考虑是否真的需要模板方法,避免“杀鸡用牛刀”。