设计模式
GoF 23种设计模式完整总结
说明:
- 分为创建型、结构型、行为型三大类;
- 按常用程度分级:⭐⭐⭐高频常用、⭐⭐偶尔使用、⭐极少使用;
- 包含:模式作用、实际业务场景、框架/中间件源码案例、易混淆模式边界区分。
- 判断模式核心原则:优先看设计意图,其次看类结构;很多框架组件会同时融合多个模式,各司其职。
1. 创建型模式(5种)
核心:对象的创建,将对象实例化与业务逻辑解耦
1.1 单例模式 Singleton ⭐⭐⭐
- 作用:保证一个类全局仅有一个实例,提供全局访问点,节约资源。
- 实现:饿汉、懒汉、DCL双重检查、静态内部类、枚举单例。
- 业务场景:配置管理器、连接管理器、全局工具管理器。
- 框架案例
- Spring:Bean默认
scope="singleton",容器级单例,DefaultSingletonBeanRegistry#singletonObjects缓存单例Bean;Spring单例≠Java单例,受容器管控。 - MyBatis:
Configuration全局配置对象单例复用。
- Spring:Bean默认
- 注意:单例Bean禁止使用成员变量保存业务状态,会线程不安全。
1.2 工厂方法 Factory Method ⭐⭐⭐
- 作用:定义创建对象抽象接口,将实例化延迟到子类;父类定义接口,子类负责new对象。
- 业务场景:同一产品有多种具体实现,由子类决定创建哪一个。
- 框架案例
- Spring:
FactoryBean接口,getObject()由子类实现生产对象;MyBatisSqlSessionFactoryBean。 - JDK:
Iterator iterator()迭代器。
- Spring:
1.3 抽象工厂 Abstract Factory ⭐⭐
- 作用:生产一组相互关联/依赖的产品族;工厂产出整套相关对象。
工厂方法:生产单个产品;抽象工厂:生产一套产品族。
- 业务场景:一套配套组件,需要成套切换。
- 框架案例
- Spring
BeanFactory:抽象工厂,定义获取Bean的接口,ApplicationContext为具体实现。 - MyBatis
SqlSessionFactory:生产SqlSession,SqlSession再生产Mapper,完整产品族。
- Spring
1.4 建造者模式 Builder ⭐⭐⭐
- 作用:分步构建复杂对象;相同构建流程可产出不同对象;适合入参多、构造复杂对象,支持链式调用。
- 业务场景:实体类参数繁多、配置对象构建。
- 框架案例
- Spring:
BeanDefinitionBuilder链式构建Bean定义。 - MyBatis:
SqlSessionFactoryBuilder构建会话工厂。 - Druid、OkHttp大量Builder配置构建。
- Spring:
1.5 原型模式 Prototype ⭐
- 作用:通过对象克隆复制生成新对象,不需要new。
- 业务场景:对象创建成本很高,复制实例。
- 框架案例
- Spring:
BeanDefinition#cloneBeanDefinition()通过克隆生成新的Bean定义副本。 - JDK:
Object#clone(),如ArrayList、HashMap等集合类重写clone()实现浅拷贝。
- Spring:
- 注意: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接口。
- SpringMVC
2.2 桥接模式 Bridge ⭐
- 作用:分离抽象层与实现层,用于多维度变化扩展,避免类爆炸。
- 业务场景:一个事物有两个独立变化维度。
- 框架案例:JDBC驱动,Driver作为桥接,上层JDBC API,下层不同数据库驱动实现。
2.3 组合模式 Composite ⭐
- 作用:树状结构,统一对待叶子节点与容器节点,部分‑整体一致对待。
- 业务场景:菜单树、组织架构树、文件目录。
- 框架案例:Spring
CompositeComponentDefinition组件定义树,持有多个嵌套的ComponentDefinition,体现部分-整体层次结构。
2.4 装饰器模式 Decorator ⭐⭐⭐
- 作用:动态给对象叠加功能;不改变原有接口;可多层嵌套包装。
核心:不改接口,增强功能,多层叠加
- 业务场景:动态叠加可选功能,替代继承扩展。
- 框架案例
- JDK IO:
BufferedInputStream装饰FileInputStream增加缓冲。 - Spring
TransactionAwareCacheDecorator给缓存增加事务支持。
- JDK IO:
2.5 外观模式 Facade(门面)⭐⭐⭐
- 作用:提供高层统一门面接口,封装内部一堆复杂子系统,降低客户端调用复杂度。
核心:封装多个子组件,对外提供简单新接口
- 业务场景:封装多个内部服务,对外提供统一API。
- 框架案例
- Spring
ApplicationContext:门面,封装BeanFactory、资源加载、事件、国际化。 - MyBatis
SqlSession:门面,封装Executor、StatementHandler等内部组件。 - SpringMVC
DispatcherServlet前端控制器。
- Spring
2.6 享元模式 Flyweight ⭐
- 作用:对象池共享复用大量细粒度对象;区分内部不变状态、外部可变状态,减少内存占用。
- 业务场景:大量重复对象需要复用。
- 框架案例
- JDK
Integer.valueOf()缓存池(-128~127):经典享元,相同数值共享同一对象。 - 线程池:广义上体现了享元的池化复用思想(复用线程减少创建销毁开销),但严格来说更偏向对象池模式,因为线程是可变的、被独占使用的,不同于享元模式强调的"共享内部状态"。
- JDK
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
InstantiationStrategyBean实例化策略。 - JDK
Comparator比较器。
- Spring
3.2 模板方法 Template Method ⭐⭐⭐
- 作用:抽象父类定义完整算法骨架、固定执行流程;部分步骤交给子类重写实现;基于继承。
核心:流程骨架固定,只有部分步骤变化
- 业务场景:一套固定流程,只有个别步骤逻辑不一样。
- 框架案例
- Spring
AbstractApplicationContext#refresh()IOC容器启动模板方法。 - Spring
JdbcTemplate、RedisTemplate:固定获取/关闭资源流程,回调留给业务。 - MyBatis
BaseExecutor,查询骨架由子类实现差异逻辑。
- Spring
3.3 观察者模式 Observer ⭐⭐⭐
- 作用:一对多依赖;目标对象状态变更,自动通知所有观察者。
核心:事件广播,所有订阅者都收到通知,无法拦截终止
- 业务场景:事件通知,消息通知,业务完成后触发多个后续动作。
- 框架案例
- Spring事件机制:
ApplicationEvent事件、ApplicationListener观察者、ApplicationEventPublisher发布器;ContextRefreshedEvent容器刷新事件。默认同步执行。
- Spring事件机制:
- 注意:观察者模式≠发布-订阅模式。观察者模式中Subject直接维护Observer列表并同步通知,耦合度较高;发布-订阅模式引入了独立的消息通道/Broker,发布者与订阅者完全解耦。MQ消息队列是发布-订阅模式的典型实现,属于观察者思想的分布式演进。
3.4 迭代器模式 Iterator ⭐⭐
- 作用:提供统一遍历集合的方式,不暴露集合底层结构。
- 业务场景:遍历不同集合数据结构。
- 框架案例 JDK
Iterator。
3.5 责任链模式 Chain of Responsibility ⭐⭐⭐
- 作用:多个处理器组成链条;请求沿着链条传递;处理器可以处理请求或传递给下一个;可以中断链条。
核心:请求链式传递,可拦截终止后续执行
- 业务场景:审批流、过滤校验、多级处理。
- 框架案例
- Servlet
Filter过滤器链。 - SpringMVC
Interceptor拦截器链。 - MyBatis
Interceptor插件链。 - Netty
ChannelPipeline处理器链。
- Servlet
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. 速记清单
- 需要做接口兼容转换 → 适配器
- 需要动态叠加功能,不改接口,可多层嵌套 → 装饰器
- 需要控制对象访问(事务、权限、延迟)不改接口 → 代理
- 多套算法可以互换替换(组合) → 策略模式
- 父类固定流程骨架,子类重写部分步骤(继承) → 模板方法
- 核心目的只是创建对象 → 工厂模式;分步构建复杂对象 → 建造者
- 封装多个复杂子系统对外简单接口 → 外观模式
- 请求沿着链条传递,可以中断 → 责任链
- 事件发布广播,全部订阅者接收,不可拦截 → 观察者
重要提醒:很多Spring组件会同时使用多个模式(例如Resource:适配器+策略;HandlerAdapter:适配器+策略选择),不同模式承担不同职责,不要强行说一个类属于某一个模式。

浙公网安备 33010602011771号