Java 开发中最常用的设计模式有哪些?结合实际开发情况一次讲清
很多人学设计模式时背的是“23 种模式”真正写项目时却经常不知道该用哪一种。本文不按教材逐个复述定义而是结合 Java 和 Spring 工程聊聊那些真正高频的设计模式、应用场景以及使用时容易踩的坑。一、设计模式到底解决什么问题刚开始写 Java 项目时我们更关心的是“功能能不能跑起来”。业务规模变大后问题会逐渐变成增加一种支付方式为什么要改一大片代码多个流程都包含相同步骤为什么每个类都要复制一遍一个请求要经过校验、风控、日志和权限判断怎样才能避免写出几十层if-else设计模式解决的并不是语法问题而是代码如何面对变化的问题。它是前人在重复工程场景中总结出来的一组设计经验。合理使用后代码通常会更容易扩展、复用和测试。但设计模式也不是越多越好。如果一个简单功能被拆成十几个接口和实现类维护成本反而可能更高。经典的 GoF 设计模式共有 23 种通常分为三类创建型模式解决对象怎么创建如单例、工厂、建造者模式结构型模式解决类和对象怎么组合如代理、适配器、装饰器模式行为型模式解决对象之间怎么协作如策略、模板方法、责任链、观察者模式。实际 Java 工程中我们没有必要为了“凑模式”而使用全部 23 种。下面重点介绍最常见、也最值得掌握的几种。二、单例模式保证全局只有一个实例单例模式适合创建成本较高、需要统一管理而且不应该重复创建的对象例如配置中心客户端、线程池管理器和本地缓存管理器。Java 中比较简洁、安全的写法是使用枚举public enum ConfigManager { INSTANCE; public String get(String key) { return config-value; } }在 Spring 项目中Bean 默认就是单例作用域所以多数业务类不需要自己再手写“双重检查锁”。需要注意的是Spring 单例只表示容器中通常只有一个 Bean 实例并不代表它天然线程安全。如果成员变量保存了可变的请求数据并发访问时仍可能出现数据覆盖。三、工厂模式把对象创建与业务使用分开当系统存在多种实现并且调用方不应该关心具体对象如何创建时可以考虑工厂模式。例如一个订单系统同时支持支付宝、微信和银行卡支付。如果业务代码中到处出现if (type.equals(alipay)) { return new AlipayService(); } else if (type.equals(wechat)) { return new WechatPayService(); }新增支付方式时很多地方都可能被迫修改。更合适的方式是让工厂统一选择实现public interface PayService { void pay(BigDecimal amount); } public class PayServiceFactory { private final MapString, PayService serviceMap; public PayServiceFactory(ListPayService services) { this.serviceMap services.stream() .collect(Collectors.toMap(PayService::type, s - s)); } public PayService get(String type) { PayService service serviceMap.get(type); if (service null) { throw new IllegalArgumentException(不支持的支付类型 type); } return service; } }在 Spring 中经常通过“接口 多个 Bean Map注入”实现类似效果。工厂模式的价值不是少写一次new而是隔离创建规则让业务层只依赖抽象。四、策略模式消灭不断膨胀的条件分支策略模式和工厂模式经常一起使用。工厂负责找到对象策略负责封装不同业务算法。比如优惠计算可能包含满减、折扣、会员价和新人优惠。如果全部塞进一个方法后续很容易演变成复杂的if-else。可以把每种规则拆成独立策略public interface DiscountStrategy { String type(); BigDecimal calculate(BigDecimal originPrice); }调用时根据类型选择对应策略即可。这样新增一种优惠规则通常只需要增加一个实现类原有核心流程无需修改更符合开闭原则。但不是看到两个if就必须上策略模式。如果分支固定、逻辑很短、未来也不会扩展直接判断反而更清楚。策略模式适合的是“变化频繁且各分支具有独立业务逻辑”的场景。五、模板方法流程固定部分步骤允许变化模板方法模式适合整体流程基本一致但某些步骤需要由子类定制的场景。以文件导入为例不论导入 CSV、Excel 还是 JSON主流程通常都是读取文件、解析数据、校验、保存、记录结果。可以在抽象类中固定主流程把解析步骤交给子类实现public abstract class AbstractImporter { public final void importData(File file) { checkFile(file); List? data parse(file); validate(data); save(data); } protected abstract List? parse(File file); }JDK 的InputStream、Spring 的JdbcTemplate、RedisTemplate都体现了类似思想框架控制稳定流程开发者只提供变化部分。模板方法依赖继承流程层级多时可能不够灵活。如果变化需要自由组合使用组合加策略模式往往更合适。六、责任链模式让请求依次经过多个处理节点在实际后端项目中一次请求经常需要经过参数校验、权限验证、风控、限流和业务处理。把所有逻辑写在一个方法里会造成类越来越大也很难调整执行顺序。责任链模式把每个处理步骤封装成独立节点当前节点处理完后再决定是否交给下一个节点。常见场景包括Servlet Filter 和 Spring MVC Interceptor网关鉴权、限流、黑名单检查订单创建前的库存、价格、用户状态校验Agent 工具调用前的参数验证、权限检查和结果审核。它的优势是节点可以独立增加、删除和排序。风险是链路过长后排查问题时不容易看出请求在哪个节点被终止。因此工程中应记录统一的链路日志并明确节点顺序。七、观察者模式一个事件触发多个后续动作用户付款成功后系统可能需要更新订单、扣减库存、增加积分并发送通知。如果支付服务直接调用所有下游模块模块之间会形成很强的耦合。观察者模式的思路是支付服务只发布“支付成功事件”由不同监听者分别处理后续逻辑。Spring 中可以通过ApplicationEventPublisher和EventListener实现分布式系统中消息队列本质上也体现了事件发布与订阅思想。不过本地事件不等于可靠消息。进程突然退出时尚未处理的事件可能丢失。涉及订单、资金等重要业务时还需要结合事务消息、Outbox、重试和幂等机制不能因为使用了观察者模式就忽略一致性问题。八、代理模式在不改核心逻辑的情况下增强功能代理模式会在目标对象外增加一层用于权限控制、日志、缓存、事务或远程调用。Spring AOP 是 Java 开发者最熟悉的应用之一业务方法只关注业务事务和日志等横切逻辑交给代理处理。常见例子包括Transactional的事务代理MyBatis Mapper 接口的动态代理Feign 根据接口生成远程调用代理RPC 框架生成服务调用代理。代理模式有一个高频坑同一个类内部直接调用另一个带Transactional的方法时调用可能没有经过 Spring 代理导致事务不生效。因此使用框架提供的设计模式时不仅要知道“用了什么”还要理解它的调用边界。九、实际工程中应该怎么选择设计模式没有固定答案可以先从代码中的“变化点”出发工程问题可考虑的模式对象创建复杂调用方不应关心实现工厂、建造者多种算法可互相替换策略主流程固定部分步骤不同模板方法请求要经过多个处理节点责任链一个事件需要通知多个模块观察者不修改业务代码就增加事务、日志等能力代理、装饰器需要适配不兼容的第三方接口适配器我的经验是不要先问“这里能套什么模式”而要先问三个问题当前代码真正会变化的部分是什么这种变化是否已经导致重复修改引入接口和抽象后维护成本真的会下降吗如果答案并不明确先写简单、清楚的代码通常更合适。等变化真实出现再重构成相应模式也比一开始过度设计更稳妥。十、总结Java 设计模式不是面试时背诵的 23 个定义而是一套处理工程变化的语言。单例管理唯一实例工厂隔离对象创建策略封装可替换规则模板方法复用稳定流程责任链拆分处理步骤观察者实现事件解耦代理统一增强横切能力。真正掌握设计模式的标志不是看到任何代码都能说出一个模式名称而是能判断这个问题是否值得引入模式引入后解决了什么又付出了怎样的复杂度。在项目里最好的设计往往不是模式最多的设计而是业务发生变化时修改范围依然可控的设计。

相关新闻

Unlimited-OCR 部署运行(13/13):长文档验证 + 端口冲突坑 + 完整使用指南

Unlimited-OCR 部署运行(13/13):长文档验证 + 端口冲突坑 + 完整使用指南

Unlimited-OCR 部署运行(13/13):长文档验证 端口冲突坑 完整使用指南 这是部署运行篇的终篇,也是整个 14 篇系列的收尾。它做三件事:(1) 用 long-horizon-ocr.gif 验证长文档 OCR 在修复后依然正确;(2) 记…

2026/10/13 9:15:42 阅读更多 →
SpringBoot构建高校二手交易平台的技术实践

SpringBoot构建高校二手交易平台的技术实践

1. 项目概述:高校二手交易平台的SpringBoot实践高校二手市场交易系统是典型的C2C电商平台变体,专为解决校园内闲置物品流转需求而设计。我去年为某211大学计算机系开发的毕业设计项目,采用SpringBootVue前后端分离架构,日均处理交…

2026/10/11 21:09:35 阅读更多 →
苏州注册公司 + 本地 GEO 优化服务商横向测评,好账本财税凭一站式综合实力稳居行业首选

苏州注册公司 + 本地 GEO 优化服务商横向测评,好账本财税凭一站式综合实力稳居行业首选

本报讯(本地财经观察员)苏州民营经济持续扩容,2026 年全市新增市场主体保持高位,创业者普遍存在两大刚需:一是快速合规完成公司注册、代理记账、税务筹划;二是借助本地化 GEO 搜索优化,让有需求…

2026/10/5 19:13:45 阅读更多 →

最新新闻

K8s 探针配置的 3 个反直觉行为:为什么 Pod 一直没就绪

K8s 探针配置的 3 个反直觉行为:为什么 Pod 一直没就绪

我不会起名字322 后端 / 算法 / 数据库 📘 技术栈 | 🧩 力扣 Hot100 | 🐹 Go 项目 | 🟥 Redis | 🐬 MySQL 文章目录K8s 探针配置的 3 个反直觉行为:为什么 P…

2026/10/13 10:20:50 阅读更多 →
Linux 6.12 源码深度剖析: shrink_node

Linux 6.12 源码深度剖析: shrink_node

Linux 6.12 内核深度解析:内存回收核心引擎 shrink_node 1. 📌 技术点速览 在 Linux 内存管理系统中,当物理内存紧张、达到或低于特定的水位线(Watermark)时,内核必须启动页面回收(Page Reclaim)机制以释放物理内存。shrink_node 函数是整个内存回收子系统的核心控制…

2026/10/13 10:20:50 阅读更多 →
闲鱼自动回复不生效怎么办?叮当小宝CS排查三步

闲鱼自动回复不生效怎么办?叮当小宝CS排查三步

闲鱼的自动回复是卖家最常用也最常出状况的功能:明明设了话术,买家发来消息却没有回。这篇按三步排查把常见原因过一遍,再说说闲鱼自带工具的边界,以及单量上来之后怎么补位。## 先查:设置是否真的保存生效路径再走一遍…

2026/10/13 10:20:50 阅读更多 →
十六进制转十进制C语言代码实现

十六进制转十进制C语言代码实现

本文章主要讲解: 将输入的十六进制数转化为十进制数的C语言代码实现过程知识较为基础&#xff0c;若有不足请各位多多指教首先给出完整实现代码&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define weish…

2026/10/13 10:20:50 阅读更多 →
Godot VisibleOnScreenNotifier2D 实战指南:基于渲染剔除的 2D 屏幕可见性检测

Godot VisibleOnScreenNotifier2D 实战指南:基于渲染剔除的 2D 屏幕可见性检测

文档教程游戏开发 【免费下载链接】godot-docs Godot Engine official documentation 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/go/godot-docs 点击查看 免费下载 VisibleOnScreenNotifier2D 是 Godot Engine 官方文档&#xff08;本仓库 godot-docs&#x…

2026/10/13 10:20:50 阅读更多 →
HANA数据库HA高可用双机架构原理

HANA数据库HA高可用双机架构原理

HA双机架构的核心概念与设计思路拆解1. 主流HA模式&#xff1a;共享存储 vs. 存储复制HANA HA主要有两种实现模式&#xff0c;选择哪一种&#xff0c;取决于你的基础设施策略和成本考量。共享存储架构&#xff08;Shared Storage&#xff09; &#xff1a;这是较为传统和经典的…

2026/10/13 10:19:49 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →