设计模式
约 1897 字大约 6 分钟
理论设计模式
2025-11-10
最常用的工厂模式和策略模式
工厂模式的关注点是如何创建对象,一般用来做决定创建哪个对象。
策略模式的关注点是如何执行算法,一般用来做决定使用哪种算法。
工厂模式和策略模式经常会结合使用。
设计模式通常被比作软件工程师之间的“通用语言”,它们不是生搬硬套的代码模板,而是解决特定场景下重复出现问题的最佳实践。为了帮你理清这 23 种经典模式(GoF 模式)的脉络,我将它们按创建型、结构型、行为型三大类进行梳理,重点解析它们的核心用途以及容易混淆的区别。
🏗️ 创建型模式:关注“对象怎么来”
这类模式的核心在于将对象的创建与使用分离,提高系统的灵活性和复用性。
| 模式名称 | 核心用途 (一句话) | 典型场景 |
|---|---|---|
| 单例模式 | 确保一个类只有一个实例,并提供全局访问点。 | 数据库连接池、日志记录器、配置管理器。 |
| 工厂方法 | 定义创建对象的接口,让子类决定实例化哪个类。 | 日志记录器、不同数据库驱动加载。 |
| 抽象工厂 | 创建一系列相关或依赖的对象家族。 | 跨平台 UI 组件(如 Windows 风格与 Mac 风格的按钮组合)。 |
| 建造者模式 | 将复杂对象的构建与表示分离,分步构建。 | 构造复杂的 DTO、XML/HTML 生成、Lombok 的 @Builder。 |
| 原型模式 | 通过复制现有对象(克隆)来创建新对象。 | 对象创建成本高(如复杂的缓存对象)、游戏存档。 |
🧩 结构型模式:关注“类与对象怎么组装”
这类模式关注如何将类或对象组合成更大的结构,在保证灵活性的同时提高代码复用性。
| 模式名称 | 核心用途 (一句话) | 典型场景 |
|---|---|---|
| 适配器模式 | 将一个类的接口转换成客户期望的另一个接口。 | 兼容旧接口、第三方 SDK 接入(如电压转换器)。 |
| 装饰器模式 | 动态地给对象添加额外的职责。 | Java IO 流、奶茶加料、日志增强。 |
| 代理模式 | 为其他对象提供代理以控制对这个对象的访问。 | 远程调用、权限控制、延迟加载(如 Spring AOP)。 |
| 外观模式 | 为子系统提供统一的入口,简化调用。 | 复杂的子系统封装(如一键启动系统、API 网关)。 |
| 组合模式 | 将对象组合成树形结构以表示“部分-整体”。 | 文件系统目录树、菜单树。 |
| 桥接模式 | 将抽象部分与实现部分分离,使它们可以独立变化。 | 不同平台的绘图工具、JDBC 驱动。 |
| 享元模式 | 运用共享技术有效地支持大量细粒度对象。 | 线程池、字符串常量池、五子棋棋子。 |
🤝 行为型模式:关注“对象之间怎么交互”
这类模式关注对象之间的职责分配和通信方式,确保系统在运行时更加灵活。
| 模式名称 | 核心用途 (一句话) | 典型场景 |
|---|---|---|
| 策略模式 | 定义一系列算法,使它们可以互相替换。 | 多种支付方式、多种排序算法、电商折扣计算。 |
| 观察者模式 | 定义一对多依赖,一个对象状态改变,所有依赖者自动通知。 | 事件驱动系统、消息队列、B 站关注 UP 主。 |
| 模板方法 | 定义算法骨架,将具体步骤延迟到子类实现。 | 框架生命周期(如 Spring Bean 初始化)、SOP 流程。 |
| 责任链模式 | 沿着处理链传递请求,多个对象都有机会处理。 | 审批流程(请假审批)、过滤器链。 |
| 命令模式 | 将请求封装为对象,支持撤销、排队。 | 菜单命令、事务回滚、遥控器按钮。 |
| 状态模式 | 允许对象在内部状态改变时改变其行为。 | 订单状态流转(待支付->已支付->发货)、TCP 连接状态。 |
| 中介者模式 | 集中化对象间的通信,减少对象间直接依赖。 | 聊天室、机场塔台、房产中介。 |
| 迭代器模式 | 顺序访问集合元素,无需暴露内部结构。 | Java 的 Iterator、数据库游标。 |
| 访问者模式 | 在不修改数据结构的前提下定义新操作。 | 编译器 AST 解析、报表生成。 |
| 备忘录模式 | 捕获对象内部状态并保存,以便恢复。 | 游戏存档/读档、Ctrl+Z 撤销。 |
| 解释器模式 | 定义语言文法并解释执行。 | SQL 解析、正则表达式引擎。 |
⚖️ 易混淆模式的区别与对比
很多模式长得很像,但解决的问题不同。以下是面试和实战中容易混淆的几组对比:
1. 适配器模式 vs 装饰器模式 vs 代理模式
这三种模式的结构非常相似(都包装了原有对象),但意图完全不同:
- 适配器模式:改变接口。目的是让不兼容的接口能一起工作(“方头接圆孔”)。
- 装饰器模式:增强功能。接口不变,但在原有功能上“加料”(“给手机贴膜”)。
- 代理模式:控制访问。接口通常不变,但在访问前后加入控制逻辑(如权限检查、延迟加载)(“经纪人代理明星”)。
2. 策略模式 vs 状态模式
- 策略模式:主动选择。客户端知道有哪些算法,并根据需求主动指定使用哪一个(如:用户选择了“支付宝支付”)。
- 状态模式:被动响应。对象的状态改变导致行为改变,客户端通常不需要知道具体是哪个状态类在起作用(如:订单状态变为“已支付”后,自动触发“发货”行为)。
3. 工厂方法模式 vs 模板方法模式
- 工厂方法模式:关注对象的创建。子类负责
new出具体的产品。 - 模板方法模式:关注算法的流程。子类负责实现流程中的具体步骤,但流程骨架由父类控制。
4. 外观模式 vs 中介者模式
- 外观模式:是单向的。它只是为子系统提供一个简单的入口,子系统之间可能还是乱成一团,但客户端变简单了。
- 中介者模式:是多向的。它关注的是让一组对象(同事类)不再互相直接通信,而是通过中介者来协调,解决了对象间的网状依赖。
5. 简单工厂 vs 工厂方法
- 简单工厂:一个工厂类生产所有产品,违反开闭原则(加新产品要改代码)。
- 工厂方法:一个工厂类只生产一种产品,符合开闭原则(加新产品只需加新工厂类)。
💡 总结建议
在实际开发中,不要为了用模式而用模式。设计模式的本质是解耦和复用。
- 如果代码逻辑清晰、没有重复、易于维护,那么不使用设计模式也是好代码。
- 当你发现代码中出现大量的
if-else、对象创建过于复杂、或者修改一个功能影响了一大片代码时,才是引入设计模式的最佳时机。
