设计模式

GoF 23种设计模式完整总结

说明:

  1. 分为创建型、结构型、行为型三大类;
  2. 按常用程度分级:⭐⭐⭐高频常用、⭐⭐偶尔使用、⭐极少使用;
  3. 包含:模式作用、实际业务场景、框架/中间件源码案例、易混淆模式边界区分。
  4. 判断模式核心原则:优先看设计意图,其次看类结构;很多框架组件会同时融合多个模式,各司其职。

1. 创建型模式(5种)

核心:对象的创建,将对象实例化与业务逻辑解耦

1.1 单例模式 Singleton ⭐⭐⭐

  • 作用:保证一个类全局仅有一个实例,提供全局访问点,节约资源。
  • 实现:饿汉、懒汉、DCL双重检查、静态内部类、枚举单例。
  • 业务场景:配置管理器、连接管理器、全局工具管理器。
  • 框架案例
    • Spring:Bean默认scope="singleton",容器级单例,DefaultSingletonBeanRegistry#singletonObjects缓存单例Bean;Spring单例≠Java单例,受容器管控。
    • MyBatis:Configuration全局配置对象单例复用。
  • 注意:单例Bean禁止使用成员变量保存业务状态,会线程不安全。

1.2 工厂方法 Factory Method ⭐⭐⭐

  • 作用:定义创建对象抽象接口,将实例化延迟到子类;父类定义接口,子类负责new对象。
  • 业务场景:同一产品有多种具体实现,由子类决定创建哪一个。
  • 框架案例
    • Spring:FactoryBean接口,getObject()由子类实现生产对象;MyBatis SqlSessionFactoryBean。
    • JDK:Iterator iterator()迭代器。

1.3 抽象工厂 Abstract Factory ⭐⭐

  • 作用:生产一组相互关联/依赖的产品族;工厂产出整套相关对象。

工厂方法:生产单个产品;抽象工厂:生产一套产品族。

  • 业务场景:一套配套组件,需要成套切换。
  • 框架案例
    • Spring BeanFactory:抽象工厂,定义获取Bean的接口,ApplicationContext为具体实现。
    • MyBatis SqlSessionFactory:生产SqlSession,SqlSession再生产Mapper,完整产品族。

1.4 建造者模式 Builder ⭐⭐⭐

  • 作用:分步构建复杂对象;相同构建流程可产出不同对象;适合入参多、构造复杂对象,支持链式调用。
  • 业务场景:实体类参数繁多、配置对象构建。
  • 框架案例
    • Spring:BeanDefinitionBuilder链式构建Bean定义。
    • MyBatis:SqlSessionFactoryBuilder构建会话工厂。
    • Druid、OkHttp大量Builder配置构建。

1.5 原型模式 Prototype ⭐

  • 作用:通过对象克隆复制生成新对象,不需要new。
  • 业务场景:对象创建成本很高,复制实例。
  • 框架案例
    • Spring:BeanDefinition#cloneBeanDefinition()通过克隆生成新的Bean定义副本。
    • JDK:Object#clone(),如ArrayList、HashMap等集合类重写clone()实现浅拷贝。
  • 注意:Spring scope="prototype"每次获取返回新对象,但其底层是通过反射new新实例而非clone,严格来说不算原型模式的实现。

2. 结构型模式(7种)

核心:类与对象组合,组装成更大的结构,实现功能扩展

2.1 适配器模式 Adapter ⭐⭐⭐

  • 作用:将已有类接口转换成客户端期望的目标接口,解决接口不兼容;分为类适配器(继承)、对象适配器(组合,主流)。

核心:改变接口,做兼容转换

  • 业务场景:对接第三方SDK,不同第三方接口格式不一样,统一适配成系统内部接口。
  • 框架案例
    • SpringMVC HandlerAdapter:适配多种Controller实现,统一handle()调用。
    • Spring AOP AdvisorAdapter适配不同通知类型。
    • MyBatis Log适配器:适配slf4j/log4j/jdk日志。
    • Spring Resource各个实现类:把File/URL/ClassPath资源适配成统一Resource接口。

2.2 桥接模式 Bridge ⭐

  • 作用:分离抽象层与实现层,用于多维度变化扩展,避免类爆炸。
  • 业务场景:一个事物有两个独立变化维度。
  • 框架案例:JDBC驱动,Driver作为桥接,上层JDBC API,下层不同数据库驱动实现。

2.3 组合模式 Composite ⭐

  • 作用:树状结构,统一对待叶子节点与容器节点,部分‑整体一致对待。
  • 业务场景:菜单树、组织架构树、文件目录。
  • 框架案例:Spring CompositeComponentDefinition组件定义树,持有多个嵌套的ComponentDefinition,体现部分-整体层次结构。

2.4 装饰器模式 Decorator ⭐⭐⭐

  • 作用:动态给对象叠加功能;不改变原有接口;可多层嵌套包装。

核心:不改接口,增强功能,多层叠加

  • 业务场景:动态叠加可选功能,替代继承扩展。
  • 框架案例
    • JDK IO:BufferedInputStream装饰FileInputStream增加缓冲。
    • Spring TransactionAwareCacheDecorator给缓存增加事务支持。

2.5 外观模式 Facade(门面)⭐⭐⭐

  • 作用:提供高层统一门面接口,封装内部一堆复杂子系统,降低客户端调用复杂度。

核心:封装多个子组件,对外提供简单新接口

  • 业务场景:封装多个内部服务,对外提供统一API。
  • 框架案例
    • Spring ApplicationContext:门面,封装BeanFactory、资源加载、事件、国际化。
    • MyBatis SqlSession:门面,封装Executor、StatementHandler等内部组件。
    • SpringMVC DispatcherServlet前端控制器。

2.6 享元模式 Flyweight ⭐

  • 作用:对象池共享复用大量细粒度对象;区分内部不变状态、外部可变状态,减少内存占用。
  • 业务场景:大量重复对象需要复用。
  • 框架案例
    • JDK Integer.valueOf()缓存池(-128~127):经典享元,相同数值共享同一对象。
    • 线程池:广义上体现了享元的池化复用思想(复用线程减少创建销毁开销),但严格来说更偏向对象池模式,因为线程是可变的、被独占使用的,不同于享元模式强调的"共享内部状态"。

2.7 代理模式 Proxy ⭐⭐⭐

  • 作用:提供代理对象控制对真实目标对象访问;可做拦截、增强、延迟、远程;分为静态代理、JDK动态代理、CGLIB代理。

核心:不改接口,控制访问;不一定增强,可以做权限、延迟、远程调用

  • 业务场景:权限校验、日志、事务、延迟加载、RPC远程调用。
  • 框架案例
    • Spring AOP:JDK动态代理(实现接口)、CGLIB代理(类代理)实现切面。
    • MyBatis MapperProxy:Mapper接口代理对象,拦截方法执行SQL。

3. 行为型模式(11种)

核心:对象之间通信、职责分配、算法封装

3.1 策略模式 Strategy ⭐⭐⭐

  • 作用:定义一组可互换的算法实现,实现同一接口;运行时动态选择算法;使用组合而非继承。

核心:整套算法可以互相替换,流程不固定

  • 业务场景:多种业务算法,运行时动态切换;例如多种支付方式、多种导出策略。
  • 框架案例
    • Spring DefaultResourceLoader根据location选择不同Resource实现。
    • 线程池拒绝策略RejectedExecutionHandler。
    • Spring InstantiationStrategy Bean实例化策略。
    • JDK Comparator比较器。

3.2 模板方法 Template Method ⭐⭐⭐

  • 作用:抽象父类定义完整算法骨架、固定执行流程;部分步骤交给子类重写实现;基于继承。

核心:流程骨架固定,只有部分步骤变化

  • 业务场景:一套固定流程,只有个别步骤逻辑不一样。
  • 框架案例
    • Spring AbstractApplicationContext#refresh() IOC容器启动模板方法。
    • Spring JdbcTemplate、RedisTemplate:固定获取/关闭资源流程,回调留给业务。
    • MyBatis BaseExecutor,查询骨架由子类实现差异逻辑。

3.3 观察者模式 Observer ⭐⭐⭐

  • 作用:一对多依赖;目标对象状态变更,自动通知所有观察者。

核心:事件广播,所有订阅者都收到通知,无法拦截终止

  • 业务场景:事件通知,消息通知,业务完成后触发多个后续动作。
  • 框架案例
    • Spring事件机制:ApplicationEvent事件、ApplicationListener观察者、ApplicationEventPublisher发布器;ContextRefreshedEvent容器刷新事件。默认同步执行。
  • 注意:观察者模式≠发布-订阅模式。观察者模式中Subject直接维护Observer列表并同步通知,耦合度较高;发布-订阅模式引入了独立的消息通道/Broker,发布者与订阅者完全解耦。MQ消息队列是发布-订阅模式的典型实现,属于观察者思想的分布式演进。

3.4 迭代器模式 Iterator ⭐⭐

  • 作用:提供统一遍历集合的方式,不暴露集合底层结构。
  • 业务场景:遍历不同集合数据结构。
  • 框架案例 JDK Iterator。

3.5 责任链模式 Chain of Responsibility ⭐⭐⭐

  • 作用:多个处理器组成链条;请求沿着链条传递;处理器可以处理请求或传递给下一个;可以中断链条。

核心:请求链式传递,可拦截终止后续执行

  • 业务场景:审批流、过滤校验、多级处理。
  • 框架案例
    • Servlet Filter过滤器链。
    • SpringMVC Interceptor拦截器链。
    • MyBatis Interceptor插件链。
    • Netty ChannelPipeline处理器链。

3.6 命令模式 Command ⭐

  • 作用:把请求封装成命令对象,可以队列、延迟、撤销执行。
  • 业务场景:任务队列、可撤销操作。

3.7 备忘录模式 Memento ⭐

  • 作用:捕获对象内部状态快照,可以恢复到历史状态。
  • 业务场景:回滚、撤销操作。

3.8 状态模式 State ⭐⭐

  • 作用:对象内部状态改变时自动改变对象行为;状态和行为绑定。
  • 业务场景:状态机,订单状态流转。

3.9 访问者模式 Visitor ⭐

  • 作用:不修改原有类,对一组对象增加额外操作;双分派。
  • 业务场景:对固定数据结构做多种不同运算。

3.10 中介者模式 Mediator ⭐

  • 作用:对象之间不直接交互,全部交给中介对象完成解耦,减少多对多依赖。
  • 业务场景:多组件交互复杂,引入中介协调。

3.11 解释器模式 Interpreter ⭐

  • 作用:定义语言文法解释规则;极少业务开发使用。
  • 业务场景:语法解析,脚本解析。

4. 常用程度总排序

⭐⭐⭐ 高频常用(业务开发、框架源码随处可见)

单例、工厂方法、建造者、适配器、装饰器、外观、代理、策略、模板方法、观察者、责任链

⭐⭐ 偶尔使用(特定场景才会用到)

抽象工厂、迭代器、状态模式

⭐ 极少使用(业务几乎不用,多见于特定底层组件)

原型、桥接、组合、享元、命令、备忘录、访问者、中介者、解释器


5. 易混淆模式对比与边界

区分第一原则:看设计意图,不是看代码结构是否包装/组合

5.1 适配器 vs 装饰器 vs 代理

模式 核心意图 接口是否变化 关键点
适配器 Adapter 接口转换,解决不兼容 改变接口 把A接口转为B接口,让异构组件协作
装饰器 Decorator 动态叠加增强功能 接口完全不变 多层嵌套叠加能力;关注增强对象能力
代理 Proxy 控制目标对象访问 接口完全不变 拦截访问;权限、延迟、远程、事务;不一定增强功能

边界:

  • 适配器:目的就是改接口做兼容。
  • 装饰器、代理接口和原始对象完全一致;装饰侧重叠加功能;代理侧重访问控制。

5.2 策略模式 vs 模板方法

模式 策略 Strategy 模板方法 Template Method
实现 组合聚合 继承
流程 整套算法替换,流程不固定 父类固定完整流程骨架,部分步骤子类实现
变化点 完整算法互换 仅个别步骤变化

边界:模板父类掌控整个执行流程;策略只是替换整套算法,没有固定流程约束。

5.3 策略模式 vs 工厂模式

策略模式 工厂模式
意图 选择业务算法,执行业务逻辑 只负责创建对象实例
关注点 拿到对象之后执行业务 只生产对象,不执行业务逻辑

边界:工厂关心new;策略关心拿到对象之后的业务行为。
例:ResourceLoader#getResource()虽然创建对象,但意图是选择资源访问算法,属于策略而非工厂。

5.4 代理 vs 外观模式

代理 外观 Facade
包装对象 包装单个目标对象 封装多个子系统一堆对象
接口 与目标对象接口一致 全新简化接口
目的 控制访问单个对象 屏蔽多组件复杂度,简化客户端调用

5.5 装饰器 vs 责任链

  • 装饰器:嵌套包装,调用是嵌套栈式调用(外层包裹内层),每层装饰器通常会在调用被包装对象方法前后添加逻辑,调用链路是递归深入再逐层返回。
  • 责任链:链式传递,调用是线性链式传递(逐个节点往后传),处理器可以中断链条,后面处理器不再执行。

边界:两者都可能存在条件判断跳过后续逻辑,核心区别在于调用拓扑结构——装饰器是层层包裹的栈式结构,责任链是线性传递的链式结构。

5.6 观察者 vs 责任链

  • 观察者:事件广播,全部观察者都会收到事件,不能拦截阻止别人接收。
  • 责任链:请求传递,可以拦截终止,后续节点不再执行。

5.7 单例 vs 享元

  • 单例:全局只有1个实例。
  • 享元:对象池,可以多个实例,共享细粒度对象。

5.8 建造者 vs 工厂

  • 工厂:一次性直接产出完整对象,不关心构造步骤。
  • 建造者:分步构建对象,适合复杂多参数对象。

6. 速记清单

  1. 需要做接口兼容转换 → 适配器
  2. 需要动态叠加功能,不改接口,可多层嵌套 → 装饰器
  3. 需要控制对象访问(事务、权限、延迟)不改接口 → 代理
  4. 多套算法可以互换替换(组合) → 策略模式
  5. 父类固定流程骨架,子类重写部分步骤(继承) → 模板方法
  6. 核心目的只是创建对象 → 工厂模式;分步构建复杂对象 → 建造者
  7. 封装多个复杂子系统对外简单接口 → 外观模式
  8. 请求沿着链条传递,可以中断 → 责任链
  9. 事件发布广播,全部订阅者接收,不可拦截 → 观察者

重要提醒:很多Spring组件会同时使用多个模式(例如Resource:适配器+策略;HandlerAdapter:适配器+策略选择),不同模式承担不同职责,不要强行说一个类属于某一个模式。

posted @ 2026-09-06 17:35  灰马非马  阅读(17)  评论(0)    收藏  举报