单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点

单例模式的核心特点

  1. 唯一实例:类只能创建一个对象实例
  2. 全局访问:提供统一的访问入口
  3. 自行实例化:类自己负责创建自己的实例
  4. 严格控制:防止外部通过new创建实例

单例模式的实现方式

1. 饿汉式(线程安全)

public class Singleton {
    // 类加载时就初始化(浪费内存)
    private static final Singleton INSTANCE = new Singleton();
    
    // 私有构造方法
    private Singleton() {}
    
    // 全局访问点
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

优点:实现简单,线程安全
缺点:类加载时就创建实例,可能造成资源浪费

2. 懒汉式(基础版,线程不安全)

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton(); // 多线程下可能创建多个实例
        }
        return instance;
    }
}

缺点:多线程环境下不安全

3. 懒汉式(同步方法,线程安全但效率低)

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    // 方法同步,影响性能
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

优点:线程安全
缺点:每次获取实例都要同步,性能差

4. 双重检查锁(DCL,推荐)

public class Singleton {
    // volatile保证可见性和有序性
    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防止指令重排序

5. 静态内部类(推荐)

public class Singleton {
    private Singleton() {}
    
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return Holder.INSTANCE; // 首次调用时加载Holder类
    }
}

优点

  • 线程安全(JVM类加载机制保证)
  • 延迟加载(调用getInstance时才初始化)
  • 实现简洁

6. 枚举式(最佳实践,推荐)

public enum Singleton {
    INSTANCE; // 枚举实例本身就是单例
    
    // 可以添加方法
    public void doSomething() {
        System.out.println("执行操作");
    }
}

优点

  • 绝对防止多实例(JVM保证)
  • 防止反射攻击
  • 自动支持序列化
  • 代码最简洁

单例模式的应用场景

  1. 配置管理:全局配置对象
  2. 日志系统:日志记录器
  3. 数据库连接池
  4. 线程池
  5. 缓存系统
  6. 设备驱动(如打印机)
  7. 状态管理(如游戏中的记分牌)

如何破坏单例及防御措施

1. 反射攻击

攻击方式

Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton newInstance = constructor.newInstance();

防御方法

private Singleton() {
    if (INSTANCE != null) {
        throw new RuntimeException("禁止反射创建实例");
    }
}

2. 序列化/反序列化

攻击方式

// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton.ser"));
oos.writeObject(Singleton.getInstance());

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton.ser"));
Singleton newInstance = (Singleton) ois.readObject();

防御方法

// 添加readResolve方法
private Object readResolve() {
    return getInstance();
}

3. 克隆攻击

防御方法

@Override
protected Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
}

单例模式最佳实践

  1. 优先选择枚举实现:简单、安全、功能完备
  2. 考虑序列化需求:如需序列化,实现readResolve方法
  3. 明确生命周期:考虑单例对象的创建和销毁时机
  4. 避免全局状态:单例可能成为"上帝对象",导致代码耦合
  5. 单元测试友好:设计时应考虑可测试性

代码示例(枚举实现)

public enum DatabaseConnection {
    INSTANCE;
    
    private Connection connection;
    
    DatabaseConnection() {
        try {
            // 初始化数据库连接
            String url = "jdbc:mysql://localhost:3306/mydb";
            this.connection = DriverManager.getConnection(url, "user", "password");
        } catch (SQLException e) {
            throw new RuntimeException("数据库连接失败", e);
        }
    }
    
    public Connection getConnection() {
        return connection;
    }
    
    // 使用示例
    public static void main(String[] args) {
        Connection conn = DatabaseConnection.INSTANCE.getConnection();
        // 使用连接...
    }
}

单例模式是设计模式中最简单但最常用的模式之一,正确实现需要考虑线程安全、反射防御、序列化等问题。根据具体场景选择合适的实现方式,枚举方式在大多数情况下是最佳选择。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐