创作者模式—单例设计模式

复制代码
想象你是一家奶茶店唯一的收银机:
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. **简单场景**:直接使用枚举式(最安全简洁)
   ```java
   public enum ServiceManager {
       INSTANCE;

       public void service() { /* ... */ }
   }
   ```

2. **延迟加载场景**:静态内部类(平衡性能与安全)
   ```java
   public class LazyService {
       private LazyService() {}

       private static class Holder {
           static final LazyService INSTANCE = new LazyService();
       }

       public static LazyService getInstance() {
           return Holder.INSTANCE;
       }
   }
   ```

3. **防御性编程**:
   ```java
   // 防止克隆破坏
   @Override
   protected Object clone() throws CloneNotSupportedException {
       throw new CloneNotSupportedException();
   }
   ```

> 🌟 **黄金法则**:
> 如果你的单例需要处理资源(文件/网络连接),优先考虑枚举或饿汉式;
> 如果是重量级对象需要懒加载,用静态内部类;
> 在框架开发中务必防御反射和序列化攻击!

单例模式就像公司唯一的CEO,确保全局决策统一。正确使用能让你的系统更健壮,滥用则会导致代码僵化——关键是根据场景找到平衡点!
相关推荐
舒克起飞了2 小时前
设计模式——单例模式
java·单例模式·设计模式
大飞pkz2 小时前
【设计模式】享元模式
开发语言·设计模式·c#·享元模式
phdsky12 小时前
【设计模式】策略模式
设计模式·策略模式
烛阴12 小时前
【TS 设计模式完全指南】构建你的专属“通知中心”:深入观察者模式
javascript·设计模式·typescript
Mr_WangAndy14 小时前
C++设计模式_创建型模式_原型模式Prototype
c++·设计模式·原型模式
哆啦code梦15 小时前
设计模式之代理模式-骆驼与巴巴羊的故事
设计模式·代理模式
贝塔实验室15 小时前
ADMM 算法的基本概念
算法·数学建模·设计模式·矩阵·动态规划·软件构建·傅立叶分析
Chan1616 小时前
【 设计模式 | 结构型模式 代理模式 】
java·spring boot·后端·设计模式·intellij-idea
大飞pkz20 小时前
【设计模式】适配器模式
开发语言·设计模式·c#·适配器模式