设计模式
1. 设计模式三分类体系
Section titled “1. 设计模式三分类体系”设计模式是针对特定软件设计情境的可重用蓝图,经典的 GoF 23 种模式被划分为以下三大类:
1.1. 创建型模式 (Creational Patterns)
Section titled “1.1. 创建型模式 (Creational Patterns)”创建型模式关注 对象的创建过程,通过将对象的创建与使用分离,使系统在对象实例化时更具弹性与通用性。
| 模式名称 | 作用与目标 | 典型工程实例 |
|---|---|---|
| 单例模式 (Singleton) | 确保一个类在全局范围内只有一个实例,并提供一个统一的访问点。 | 配置文件管理器、线程池、全局日志收集器。 |
| 工厂方法模式 (Factory Method) | 定义一个用于创建对象的接口,让子类决定实例化哪一个具体类,实现延迟实例化。 | 数据库连接库(定义抽象连接,具体连接由 MySQL/PostgreSQL 驱动子类决定)。 |
| 抽象工厂模式 (Abstract Factory) | 提供一个接口,用于创建一系列相关或相互依赖的对象族,而无须指定它们具体的具体类。 | 跨平台 UI 皮肤库(同时创建 Windows 风格的按钮和文本框,或 macOS 风格 the 同类组件)。 |
| 建造者模式 (Builder) | 将一个复杂对象的构建步骤与其最终表示分离,使同样的构建过程可以创建不同的表示。 | 带有大量可选配置参数的复杂对象构造(如 HttpClientConfig、SQLQueryBuilder)。 |
| 原型模式 (Prototype) | 通过复制(克隆)已有实例来创建新的对象,而不是通过常规构造器实例化。 | 涉及昂贵资源创建的对象(如复杂数据结构),通过浅克隆/深克隆提升性能。 |
1.2. 结构型模式 (Structural Patterns)
Section titled “1.2. 结构型模式 (Structural Patterns)”结构型模式关注 类或对象的组合,旨在通过封装、代理或桥接方式将对象组合成更大、更灵活的结构。
| 模式名称 | 作用与目标 | 典型工程实例 |
|---|---|---|
| 适配器模式 (Adapter) | 将一个类的接口转换成客户端所期待的另一个接口,使原本接口不兼容的类能协同工作。 | 将第三方支付 API(如旧版 XML 接口)适配为系统内部的统一 JSON 接口。 |
| 装饰器模式 (Decorator) | 动态地给一个对象添加额外的职责。相比直接继承,装饰器提供了更灵活的扩展方式。 | I/O 输入输出流(如 Java 中的 BufferedInputStream 装饰 FileInputStream)。 |
| 代理模式 (Proxy) | 为另一个对象提供一个替身或占位符,以控制、过滤或延迟对这个真实对象的访问。 | 虚拟代理(大图片延迟加载)、安全保护代理(权限校验)、AOP 动态代理。 |
| 组合模式 (Composite) | 将对象组合成树形结构以表示“部分-整体”的层次关系,让客户端对单个对象和组合对象保持一致的使用方式。 | 文件系统管理(文件夹包含文件和子文件夹)、XML/HTML DOM 树解析。 |
| 桥接模式 (Bridge) | 将抽象部分与它的实现部分分离,使它们都可以独立地发生维度上的变化。 | 图形形状(圆、方)与不同渲染平台(OpenGL、DirectX)的多维度独立变化。 |
| 享元模式 (Flyweight) | 运用共享技术高效支持大量细粒度对象的复用,极大减少内存占用。 | 字符对象池(如 Word 编辑器中的字符对象)、JVM 中的 String 常量池。 |
| 外观模式 (Facade) | 为子系统中的一组接口提供一个统一的高层接口,使该子系统更容易被外部客户端使用。 | 复杂的微服务调用链整合(如将下单、扣减库存、物流接口合并为一个 Facade 接口)。 |
1.3. 行为型模式 (Behavioral Patterns)
Section titled “1.3. 行为型模式 (Behavioral Patterns)”行为型模式关注 对象之间的通信与职责分配,以及算法的封装和协作流程。
| 模式名称 | 作用与目标 | 典型工程实例 |
|---|---|---|
| 观察者模式 (Observer) | 定义对象间的一对多依赖关系。当一个对象状态改变时,所有依赖者都会自动收到通知并更新。 | 事件驱动系统(Event Broker)、GUI 事件监听器、发布-订阅模型。 |
| 策略模式 (Strategy) | 定义一系列算法并将其逐个封装,使它们可以动态相互替换。算法的变化不影响使用方的逻辑。 | 多支付方式选择(支付宝、微信、银联)、不同压缩格式(ZIP、RAR)的动态切换。 |
| 模板方法模式 (Template Method) | 定义一个算法的骨架,而将一些可变步骤延迟到子类中实现。子类可以在不改变整体算法结构的前提下重定义特定步骤。 | 通用的数据解析器流程(打开连接 -> 解析数据 -> 关闭连接),具体解析由 XML/JSON 子类实现。 |
| 命令模式 (Command) | 将请求封装为独立的对象,从而支持请求队列、撤销操作(Undo)及宏命令。 | 文本编辑器中各种菜单操作的封装、线程池工作队列中的 Task 对象。 |
| 迭代器模式 (Iterator) | 提供一种方法顺序访问一个聚合对象中的各个元素,而又无须暴露该聚合对象的内部物理表示。 | 集合框架(List、Set、Map)的 iterator() 遍历机制。 |
| 职责链模式 (Chain of Responsibility) | 避免请求发送者和接收者发生耦合,将多个处理者连接成一条链,请求沿着链传递直至被处理。 | Web 服务器中的 Filter 过滤器链、日志记录级别过滤系统、多级请假审批流。 |
| 备忘录模式 (Memento) | 在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便未来将其恢复到该先前状态。 | 文本编辑器的撤销(Ctrl+Z)历史记录、游戏内的存档/读档机制。 |
| 状态模式 (State) | 允许一个对象在其内部状态改变时改变其行为,看起来就像改变了其对应的类。 | 自动售货机状态机(未投币、已投币、售出中)、电梯运行状态控制。 |
| 访问者模式 (Visitor) | 表示一个作用于某对象结构中各元素的操作,允许在不改变元素类的前提下定义作用于这些元素的新操作。 | 编译器的 AST(抽象语法树)遍历分析(语义检查、代码格式化、优化器)。 |
| 中介者模式 (Mediator) | 用一个中介对象来封装一系列对象的交互,使各个对象无须显式相互引用,降低系统耦合度。 | 机场飞行交通管制系统、微服务架构中的 ESB/中介服务。 |
| 解释器模式 (Interpreter) | 给定一门语言,定义它的文法表示,并定义一个解释器,用于解释该语言中的句子。 | 正则表达式引擎、SQL 语法解析器、简单数学公式计算器。 |
2. 核心设计模式对比分析
Section titled “2. 核心设计模式对比分析”2.1. 简单工厂 Vs 工厂方法 Vs 抽象工厂
Section titled “2.1. 简单工厂 Vs 工厂方法 Vs 抽象工厂”- 简单工厂: 并非 GoF 标准模式。由一个统一的工厂类根据输入参数决定创建哪一种产品,违反开闭原则(新增产品需修改工厂类代码)。
- 工厂方法: 每个具体产品都对应一个具体工厂类。通过多态解耦:具体具体工厂只关注单类产品的创建,职责单一,符合开闭原则。
- 抽象工厂: 解决产品族(多类相关联的产品)的创建问题。例如同时生产一个系统主题下的 Button、Border 和 Window。
2.2. 策略模式 Vs 桥接模式
Section titled “2.2. 策略模式 Vs 桥接模式”- 桥接模式: 属于 结构型模式,主要用于 解耦抽象与实现,处理两个甚至多个维度独立变化的情况,目的是避免由于多维度继承带来的类爆炸。
- 策略模式: 属于 行为型模式,主要用于 封装可变算法,让客户端能够动态地切换和替换具体业务行为,目的是消除复杂的
if-else条件判断。
2.3. 建造者模式 Vs 模板方法模式
Section titled “2.3. 建造者模式 Vs 模板方法模式”- 建造者模式: 属于 创建型模式,专注于 复杂对象的组装与创建过程,通过 Director 编排具体建造步骤来产出最终对象。
- 模板方法模式: 属于 行为型模式,专注于 算法逻辑流程的控制,在父类确定一个行为骨架,部分步骤留给子类在运行时填充。
3. 重构拓展:消除代码坏味道
Section titled “3. 重构拓展:消除代码坏味道”在重构指南中,Martin Fowler 指出 “过长的方法”(Long Method) 是最经典的代码坏味道之一。方法如果过于冗长,往往意味着它承担了过多的职责,导致系统极难维护。