Java 23 种设计模式:从踩坑到精通 | 番外:单例模式 —— 全局唯一物流配置中心实战
Java 23 种设计模式从踩坑到精通 | 番外单例模式 —— 全局唯一物流配置中心实战摘要单例模式确保一个类在全局只有一个实例常用于管理配置、连接池等共享资源。本文结合智能物流中的“全局物流配置中心”场景从双重检查锁DCL、静态内部类到枚举实现完整展示单例的 5 种写法同时深入剖析多线程安全、反射攻击、反序列化陷阱等踩坑点并给出 Spring 环境下的替代方案帮你彻底掌握“全局唯一”的设计精髓。《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 正篇Singleton —— 你写的单例真的安全吗 当前番外 · 单例模式 × 物流配置中心 返回系列总目录1. 物流配置中心的痛点在物流平台中全局配置中心需要被订单服务、追踪服务、调度服务等多个模块共享。如果每个模块都自己创建配置实例会导致配置信息不一致、内存浪费、文件重复读取等问题。单例模式可以确保全局只有一个配置中心实例所有模块共享同一份配置数据。2. 单例模式 UML物流场景版3. 完整源码实现3.1 单例类物流配置中心DCL 实现importjava.util.HashMap;importjava.util.Map;/** * 单例类物流配置中心 * 使用双重检查锁Double-Checked Locking实现线程安全的懒加载单例 */publicclassLogisticsConfigCenter{// volatile 保证多线程下的可见性和禁止指令重排序privatestaticvolatileLogisticsConfigCenterinstance;// 锁对象privatestaticfinalObjectlocknewObject();// 配置存储privatefinalMapString,StringconfigMap;/** * 私有构造方法防止外部实例化 */privateLogisticsConfigCenter(){System.out.println([单例] 正在初始化物流配置中心...);this.configMapnewHashMap();// 模拟从配置文件/配置中心加载配置loadDefaultConfig();}/** * 加载默认配置模拟从配置中心读取 */privatevoidloadDefaultConfig(){configMap.put(api.key.sms,SMS_2026_ALIYUN_KEY);configMap.put(api.key.map,MAP_2026_GAODE_KEY);configMap.put(thread.pool.size,20);configMap.put(warehouse.endpoint,https://warehouse.logistics.com/api);configMap.put(tracking.endpoint,https://tracking.logistics.com/api);configMap.put(order.timeout.minutes,30);}/** * 获取单例实例双重检查锁实现 * return 全局唯一的配置中心实例 */publicstaticLogisticsConfigCentergetInstance(){// 第一次检查避免不必要的同步if(instancenull){synchronized(lock){// 第二次检查确保只有一个线程创建实例if(instancenull){instancenewLogisticsConfigCenter();}}}returninstance;}/** * 获取配置项 */publicStringgetApiKey(Stringservice){returnconfigMap.get(api.key.service);}publicintgetThreadPoolSize(){returnInteger.parseInt(configMap.getOrDefault(thread.pool.size,10));}publicStringgetWarehouseEndpoint(){returnconfigMap.get(warehouse.endpoint);}/** * 刷新配置模拟动态刷新 */publicvoidrefreshConfig(){System.out.println([单例] 正在刷新配置...);configMap.clear();loadDefaultConfig();System.out.println([单例] 配置刷新完成);}/** * 防止反序列化破坏单例 */privateObjectreadResolve(){returngetInstance();}}3.2 客户端 A订单处理服务/** * 客户端A订单处理服务 */publicclassOrderProcessingService{publicvoidprocessOrder(StringorderId){System.out.println(\n【订单处理】处理订单orderId);// 从单例配置中心获取配置LogisticsConfigCenterconfigLogisticsConfigCenter.getInstance();intpoolSizeconfig.getThreadPoolSize();StringwarehouseEndpointconfig.getWarehouseEndpoint();System.out.println( → 线程池大小poolSize);System.out.println( → 仓库服务地址warehouseEndpoint);System.out.println( → 订单处理完成 ✓);}}3.3 客户端 B物流追踪服务/** * 客户端B物流追踪服务 */publicclassTrackingService{publicvoidtrackPackage(StringtrackingNo){System.out.println(\n【物流追踪】追踪单号trackingNo);// 从同一个单例配置中心获取配置LogisticsConfigCenterconfigLogisticsConfigCenter.getInstance();StringtrackingEndpointconfig.getApiKey(map);System.out.println( → 地图API KeytrackingEndpoint);System.out.println( → 追踪信息已更新 ✓);}}3.4 完整测试验证/** * 测试类验证单例的唯一性 */publicclassSingletonTest{publicstaticvoidmain(String[]args)throwsInterruptedException{System.out.println( 单例模式物流配置中心 \n);// 验证1多次获取实例地址应该相同LogisticsConfigCenterc1LogisticsConfigCenter.getInstance();LogisticsConfigCenterc2LogisticsConfigCenter.getInstance();System.out.println(\n[验证1] 实例地址是否相同);System.out.println( c1 c1);System.out.println( c2 c2);System.out.println( c1 c2 ? (c1c2));// 验证2多线程环境下是否仍为单例System.out.println(\n[验证2] 多线程获取实例...);Threadt1newThread(()-{LogisticsConfigCenterinstanceLogisticsConfigCenter.getInstance();System.out.println( 线程1获取实例instance);});Threadt2newThread(()-{LogisticsConfigCenterinstanceLogisticsConfigCenter.getInstance();System.out.println( 线程2获取实例instance);});t1.start();t2.start();t1.join();t2.join();// 验证3不同业务模块使用同一个配置中心System.out.println(\n[验证3] 不同模块共享配置中心...);OrderProcessingServiceorderServicenewOrderProcessingService();TrackingServicetrackingServicenewTrackingService();orderService.processOrder(ORD20260723001);trackingService.trackPackage(TRACK20260723001);}}4. 运行结果 单例模式物流配置中心 [单例] 正在初始化物流配置中心... [验证1] 实例地址是否相同 c1 LogisticsConfigCenter1b6d3586 c2 LogisticsConfigCenter1b6d3586 c1 c2 ? true [验证2] 多线程获取实例... 线程1获取实例LogisticsConfigCenter1b6d3586 线程2获取实例LogisticsConfigCenter1b6d3586 [验证3] 不同模块共享配置中心... 【订单处理】处理订单ORD20260723001 → 线程池大小20 → 仓库服务地址https://warehouse.logistics.com/api → 订单处理完成 ✓ 【物流追踪】追踪单号TRACK20260723001 → 地图API KeyMAP_2026_GAODE_KEY → 追踪信息已更新 ✓5. 单例的五种实现对比实现方式线程安全懒加载推荐度说明饿汉式✅❌⭐⭐类加载时创建简单但浪费资源懒汉式同步方法✅✅⭐⭐每次访问都加锁性能差双重检查锁DCL✅✅⭐⭐⭐⭐⭐兼顾性能与线程安全推荐静态内部类✅✅⭐⭐⭐⭐⭐利用类加载机制简洁优雅枚举✅✅⭐⭐⭐⭐⭐天生防反射/序列化攻击静态内部类实现另一种推荐写法publicclassLogisticsConfigCenter{privateLogisticsConfigCenter(){/* 初始化 */}privatestaticclassHolder{privatestaticfinalLogisticsConfigCenterINSTANCEnewLogisticsConfigCenter();}publicstaticLogisticsConfigCentergetInstance(){returnHolder.INSTANCE;}}枚举实现最安全publicenumLogisticsConfigCenter{INSTANCE;publicvoiddoSomething(){/* 业务方法 */}}6. 单例模式的“坑”与防御攻击方式防御手段反射构造器内判断实例是否已存在抛异常序列化实现readResolve()返回已有实例克隆重写clone()抛异常或返回自身7. 单例模式 vs Spring Bean对比项手写单例Spring singleton scope实现方式代码层面保证容器层面保证测试友好度差好支持依赖注入和 Mock推荐场景简单工具类企业级项目首选 在 Spring 项目中优先使用容器的 singleton scope而不是手写单例。8. 六大设计原则体现原则体现单一职责配置中心只负责管理配置开闭原则可通过枚举、静态内部类扩展实现里氏替换枚举单例可替换父类依赖倒置Spring 容器依赖抽象而非具体单例接口隔离通过getInstance暴露最小接口迪米特法则客户端只需知道getInstance一个入口单例模式 UML源代码物流场景版startuml title Java 23 种设计模式从踩坑到精通 footer 折哥 | 智能物流与Java实战 skinparam backgroundColor #FEFEFE skinparam shadowing false skinparam classBorderColor #333333 skinparam classFontColor #1A1A1A skinparam classFontSize 14 skinparam noteFontSize 12 skinparam noteFontColor #555555 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 class LogisticsConfigCenter { - {static} volatile instance : LogisticsConfigCenter - {static} final Object lock - LogisticsConfigCenter() {static} getInstance() : LogisticsConfigCenter -- String getApiKey(String service) int getThreadPoolSize() String getWarehouseEndpoint() void refreshConfig() } note right of LogisticsConfigCenter b单例类Singleton/b -- 全局唯一的物流配置中心 统一管理所有物流服务的配置信息 采用双重检查锁DCL实现线程安全 end note class OrderProcessingService { void processOrder(String orderId) } note right of OrderProcessingService b客户端Client/b -- 多个业务模块通过 getInstance() 获取同一个配置中心实例 end note class TrackingService { void trackPackage(String trackingNo) } note right of TrackingService b客户端Client/b -- 追踪服务同样共享同一个 配置中心实例 end note OrderProcessingService .. LogisticsConfigCenter : 获取配置 TrackingService .. LogisticsConfigCenter : 获取配置 enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录正篇Singleton —— 你写的单例真的安全吗当前番外 · 单例模式 × 物流配置中心你在这里创建型模式汇总结构型模式汇总行为型模式汇总 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。 除了设计模式我也在深挖智能物流实战WMS、托盘调度、机器学习落地。欢迎点击头像看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通思路可鉴。

相关新闻

【claude code实践】 Claude Code Hooks 入门:在关键节点自动执行动作

【claude code实践】 Claude Code Hooks 入门:在关键节点自动执行动作

Claude Code Hooks 入门:在关键节点自动执行动作 引言:为什么现在需要理解它 如果你最近和 AI 编码助手打过交道,大概率经历过这样一种割裂感:它在对话里生成了看起来非常合理的代码,但你依然需要手动把它粘贴到编辑器…

2026/10/16 16:01:26 阅读更多 →
光电幕墙简介

光电幕墙简介

光电幕墙 光电幕墙,即粘贴在玻璃上,镶嵌于两片玻璃之间,通过电池可将光能转化成电能。这就是--太阳能光电幕墙。它是用光电池、光电板技术,把太阳光转化为电能,它关键的技术是太阳能光电池技术。太阳能光电池是利用太阳光的光子能量,使得被照射的电解液或者半导体材料的电…

2026/10/16 14:40:26 阅读更多 →
工业一体机Linux系统部署实战:从系统安装到工业通信环境搭建

工业一体机Linux系统部署实战:从系统安装到工业通信环境搭建

工业一体机是面向工业场景的集成化计算终端,通常预装Windows或Linux操作系统,支持串口通信、GPIO控制、工业总线协议等工业级接口。在ARM架构工业一体机上部署Linux系统并搭建工业通信开发环境,是工业自动化项目的常见基础工作。之前在项目里…

2026/10/19 14:54:09 阅读更多 →

最新新闻

汽车出海车载eSIM选型指南:四类供应商模式与落地避坑

汽车出海车载eSIM选型指南:四类供应商模式与落地避坑

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

2026/10/21 2:03:39 阅读更多 →
UniHacker 使用指南:3 步完成 Unity 4.x–2022.1 与 Unity Hub 的许可证修补

UniHacker 使用指南:3 步完成 Unity 4.x–2022.1 与 Unity Hub 的许可证修补

UniHacker 使用指南:3 步完成 Unity 4.x–2022.1 与 Unity Hub 的许可证修补 【免费下载链接】UniHacker 为Windows、MacOS、Linux和Docker修补所有版本的Unity3D和UnityHub 项目地址: https://gitcode.com/GitHub_Trending/un/UniHacker 打开已装好的国际版…

2026/10/21 2:03:39 阅读更多 →
并发安全内容

并发安全内容

JUC包下并发安全使用的类 线程池 ThreadPoolExecutorExecutors 并发集合类 ConcurrentHashMapCopyOnWriteArrayList 同步工具类 CountDownLatchCyclicBarrierSemaphore 原子类 AtomicIntegerAtomicReference Java中常用的锁和使用场景 内置锁(synchronized&#xff…

2026/10/21 2:03:39 阅读更多 →
ESP8285电机控制器MQTT上云实战:硬件选型、固件架构与MQTTX联调

ESP8285电机控制器MQTT上云实战:硬件选型、固件架构与MQTTX联调

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

2026/10/21 2:03:39 阅读更多 →
从下载到第一张卫星图,SatDump实操全流程

从下载到第一张卫星图,SatDump实操全流程

从下载到第一张卫星图,SatDump实操全流程 【免费下载链接】SatDump A generic satellite data processing software. 项目地址: https://gitcode.com/GitHub_Trending/sa/SatDump 手上有 RTL-SDR,频谱上却只看得见瀑布图的色块?缺的就…

2026/10/21 2:03:39 阅读更多 →
Terminal-Bench完整指南:4步跑通你的第一个AI终端评测

Terminal-Bench完整指南:4步跑通你的第一个AI终端评测

Terminal-Bench完整指南:4步跑通你的第一个AI终端评测 【免费下载链接】terminal-bench-1 A benchmark for LLMs on complicated tasks in the terminal 项目地址: https://gitcode.com/GitHub_Trending/tb/terminal-bench-1 你的Agent演示很精彩&#xff0c…

2026/10/21 2:02:39 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →