想象你是一家奶茶店唯一的收银机:
1. 所有员工必须用同一台收银机结账
2. 避免出现多台收银机导致账目混乱
3. 需要时直接使用,无需每次重新安装这就是单例模式的核心:**确保一个类只有一个实例,并提供全局访问点**。一、单例模式四大金刚(实现方式)#### 1. 🍔 饿汉式(静态变量)
```java
// 就像早餐店提前做好的包子
public class singleton {private static singleton instance = new singleton(); // 类加载就创建private singleton() {} // 锁死构造函数public static singleton getInstance() {return instance; // 直接享用现成的}
}
```
- ✅ 优点:简单粗暴线程安全
- ❌ 缺点:可能造成资源浪费(不用也创建)#### 2. 🍜 懒汉式(双重检查锁)
```java
// 像现点现做的拉面师傅
public class demo2 {private static volatile demo2 instance; // volatile防指令重排private demo2() {}public static demo2 getInstance() {if(instance == null) { // 第一次检查:避免不必要的锁synchronized(demo2.class) { // 加锁制作if(instance == null) { // 第二次检查:防穿透instance = new demo2();}}}return instance; // 热腾腾的拉面出锅}
}
```
- ✅ 优点:延迟加载+线程安全+高性能
- ⚠️ 注意:必须加 `volatile` 防止指令重排序#### 3. 🧩 静态内部类(完美方案)
```java
// 像智能外卖柜,需要时才取餐
public class demo1 {private demo1() {}private static class Holder { // 外卖柜static final demo1 INSTANCE = new demo1();}public static demo1 getInstance() {return Holder.INSTANCE; // 开柜取餐}
}
```
- ✅ 优点:懒加载+线程安全+无锁高性能
- 💡 原理:JVM保证类加载的线程安全性#### 4. 👑 枚举式(终极防御)
```java
// 像银行金库,绝对安全
public enum BankVault {INSTANCE; // 天生单例public void operation() { /* 业务方法 */ }
}
```
- ✅ 优点:防反射+防序列化破坏
- 🏆《Effective Java》推荐的首选方式---### 二、实战运用场景1. **配置管理器**(全局唯一配置)
```java
public class ConfigLoader {private static ConfigLoader instance;private Properties config;private ConfigLoader() {loadConfig(); // 加载配置文件}public static ConfigLoader getInstance() {if(instance == null) {synchronized(ConfigLoader.class) {if(instance == null) instance = new ConfigLoader();}}return instance;}public String getConfig(String key) {return config.getProperty(key);}
}
```2. **数据库连接池**(共享连接资源)
```java
public class ConnectionPool {private static final ConnectionPool INSTANCE = new ConnectionPool();private List<Connection> connections = new ArrayList<>();private ConnectionPool() {initializePool(); // 初始化连接池}public static ConnectionPool getInstance() {return INSTANCE;}public Connection getConnection() { /* ... */ }
}
```3. **日志记录器**(统一日志输出)
```java
public enum Logger {INSTANCE;public void log(String message) {System.out.println("[LOG] " + LocalDateTime.now() + ": " + message);}
}// 使用
Logger.INSTANCE.log("用户登录成功");
```---### 三、避坑指南(注意事项)1. **序列化破坏防御**(添加readResolve方法)
```java
// 在静态内部类实现中
private Object readResolve() {return Holder.INSTANCE; // 告诉序列化机制返回已有实例
}
```2. **反射攻击防御**(构造器加固)
```java
private demo() {if(instance != null) { // 双重检查锁实现中throw new IllegalStateException("单例已存在!");}
}
```3. **多线程环境**:- 饿汉式/枚举式天生线程安全- 懒汉式务必使用双重检查锁- 避免在getInstance()方法上加synchronized(性能杀手)4. **类加载器问题**:- 在OSGi等复杂类加载环境下- 使用上下文类加载器确保唯一性---### 四、各实现方式性能对比
| 实现方式 | 线程安全 | 延迟加载 | 防反射 | 防序列化 | 性能 |
|----------------|----------|----------|--------|----------|------|
| 饿汉式 | ✅ | ❌ | ❌ | ❌ | ⭐⭐⭐⭐ |
| 同步方法懒汉式 | ✅ | ✅ | ❌ | ❌ | ⭐ |
| 双重检查锁 | ✅ | ✅ | ❌ | ❌ | ⭐⭐⭐ |
| 静态内部类 | ✅ | ✅ | ❌ | ❌ | ⭐⭐⭐⭐|
| **枚举式** | ✅ | ❌ | ✅ | ✅ | ⭐⭐⭐⭐|> 💡 实际选择建议:优先选择枚举式,需要延迟加载时用静态内部类---### 五、最佳实践总结1. **简单场景**:直接使用枚举式(最安全简洁)```javapublic enum ServiceManager {INSTANCE;public void service() { /* ... */ }}```2. **延迟加载场景**:静态内部类(平衡性能与安全)```javapublic class LazyService {private LazyService() {}private static class Holder {static final LazyService INSTANCE = new LazyService();}public static LazyService getInstance() {return Holder.INSTANCE;}}```3. **防御性编程**:```java// 防止克隆破坏@Overrideprotected Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException();}```> 🌟 **黄金法则**:
> 如果你的单例需要处理资源(文件/网络连接),优先考虑枚举或饿汉式;
> 如果是重量级对象需要懒加载,用静态内部类;
> 在框架开发中务必防御反射和序列化攻击!单例模式就像公司唯一的CEO,确保全局决策统一。正确使用能让你的系统更健壮,滥用则会导致代码僵化——关键是根据场景找到平衡点!