文章目录
- [一、什么是 Java 中的单例模式(Singleton)](#一、什么是 Java 中的单例模式(Singleton))
- [二、Java 中常见的单例实现方式](#二、Java 中常见的单例实现方式)
- 三、单例模式在真实项目中的使用场景
- 四、单例模式的优缺点总结
- 五、除了单例,还有哪些常见设计模式?
- 六、总结
在 Java 后端开发中, 设计模式 几乎是绕不开的话题。
不论是日常业务开发、系统重构,还是技术面试,设计模式都会被反复提及。
但很多时候,我们停留在"知道名字、会背定义",却说不清楚:
- 这个模式 为什么要用?
- 什么时候用才合适?
- 在真实项目中 到底解决了什么问题?
一、什么是 Java 中的单例模式(Singleton)
1️⃣ 定义
单例模式是一种创建型设计模式,其核心目标是:
保证一个类在 JVM 中只有一个实例,并提供一个全局访问点。
通俗理解就是:
- 这个类只能创建一个对象
- 对象由自己控制创建
- 外部通过统一入口访问
二、Java 中常见的单例实现方式
1、饿汉式(线程安全)
java
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
优点
- 实现简单
- 天然线程安全
缺点
- 类加载时就创建实例
- 如果对象创建成本高,可能造成资源浪费
2、懒汉式(双重检查锁,推荐)
java
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
关键点说明:
volatile防止指令重排- 双重
if判断减少不必要的同步开销
这是企业级项目中非常常见的一种写法
3、静态内部类(最优雅)
java
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
特点:
- 懒加载
- 线程安全
- 无需显式加锁,性能好
在很多场景下,这是综合性最优的单例实现方式。
4、枚举单例(最安全)
java
public enum Singleton {
INSTANCE;
}
优点:
- 天然防反射
- 天然防反序列化
- 《Effective Java》官方推荐
不足:
- 不够灵活
- 不适合复杂初始化逻辑
三、单例模式在真实项目中的使用场景
1️⃣ Spring 中的单例 Bean
java
@Service
public class UserService {
}
- Spring 默认
scope = singleton - 容器中只存在一个实例
- 所有请求共享该对象
这其实是我们每天都在使用、却容易忽略的单例模式。
2️⃣ 数据库连接池 / 线程池
java
DataSource dataSource;
ExecutorService executorService;
使用单例的原因很明确:
- 创建成本高
- 需要全局共享
- 需要统一管理资源
频繁创建只会带来性能和稳定性问题。
3️⃣ 工具类 / 管理类
java
LogManager
ConfigManager
RedisClient
例如:
- Redis 客户端管理
- MinIO Client
- MQ Producer / Consumer 管理器
这些类通常:
- 不保存业务状态
- 被多个模块复用
- 非常适合单例模式
4️⃣ JVM 级别资源
java
Runtime.getRuntime();
典型代表包括:
RuntimeSystemLogger
这些都是 JVM 级别的全局唯一资源。
四、单例模式的优缺点总结
✅ 优点
- 减少对象创建,节省内存
- 统一管理共享资源
- 使用方便,全局可访问
❌ 缺点
- 隐式依赖,不利于单元测试
- 容易膨胀为"上帝类"
- 多线程场景下实现复杂
单例模式不是银弹,关键在于是否用在合适的地方。
五、除了单例,还有哪些常见设计模式?
创建型模式
| 模式 | 使用场景 |
|---|---|
| Singleton | 全局唯一实例 |
| Factory | 封装对象创建 |
| Abstract Factory | 创建产品族 |
| Builder | 构建复杂对象 |
| Prototype | 对象复制 |
结构型模式
| 模式 | 使用场景 |
|---|---|
| Proxy | AOP、权限、事务 |
| Decorator | 功能增强 |
| Adapter | 接口不兼容 |
| Facade | 对外统一入口 |
| Composite | 树形结构 |
行为型模式
| 模式 | 使用场景 |
|---|---|
| Strategy | 不同算法切换 |
| Template Method | 固定流程,步骤可变 |
| Observer | 事件通知 |
| Chain of Responsibility | 过滤器、拦截器 |
| State | 状态机、流程流转 |
六、总结
- 单例模式是最常见、也最容易被滥用的设计模式
- 真正重要的不是"会写代码",而是"知道什么时候该用"
- 设计模式的本质是:让系统更容易维护和扩展