如何实现单例模式?

访客 python案例 1

本文目录导读:

  1. 饿汉式(线程安全)
  2. 懒汉式(线程不安全)
  3. 懒汉式(同步方法)
  4. 双重检查锁定(DCL)
  5. 静态内部类
  6. 枚举实现
  7. 完整示例:枚举方式
  8. 防止反射攻击
  9. 选择建议

我来详细介绍单例模式的几种常见实现方式,每种都有其适用场景和特点。

饿汉式(线程安全)

public class Singleton {
    // 类加载时就创建实例
    private static final Singleton INSTANCE = new Singleton();
    // 私有构造函数
    private Singleton() {}
    // 全局访问点
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

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

懒汉式(线程不安全)

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

缺点: 线程不安全,多个线程同时访问会创建多个实例

懒汉式(同步方法)

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

优点: 线程安全 缺点: 每次调用都同步,性能开销大

双重检查锁定(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;
    }
}

优点: 线程安全,延迟加载,性能好 缺点: 实现较复杂

静态内部类

public class Singleton {
    private Singleton() {}
    // 静态内部类只有在使用时才会加载
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

优点: 线程安全,延迟加载,实现简单 推荐使用: 这是最常用的实现方式

枚举实现

public enum Singleton {
    INSTANCE;
    public void doSomething() {
        // 业务方法
    }
}

优点:

  • 线程安全
  • 防止反序列化创建新实例
  • 防止反射攻击
  • 实现最简单

推荐使用: 这是《Effective Java》推荐的最佳方式

完整示例:枚举方式

// 定义枚举单例
public enum DatabaseConnectionPool {
    INSTANCE;
    private ConnectionPool pool;
    DatabaseConnectionPool() {
        // 初始化连接池
        pool = new ConnectionPool(10);
    }
    public Connection getConnection() {
        return pool.getConnection();
    }
    // 使用示例
    public static void main(String[] args) {
        Connection conn = DatabaseConnectionPool.INSTANCE.getConnection();
        // 使用连接...
    }
}

防止反射攻击

对于非枚举实现,需要防止反射攻击:

public class Singleton {
    private static volatile Singleton instance;
    private static boolean initialized = false;
    private Singleton() {
        if (initialized) {
            throw new RuntimeException("单例模式禁止反射创建实例");
        }
        initialized = true;
    }
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

选择建议

场景 推荐方式
简单场景,不介意加载时创建 饿汉式
需要延迟加载 静态内部类
防止反射/序列化破坏 枚举
性能要求高 DCL或静态内部类

最佳实践: 如果你不需要特殊需求,枚举方式是最简单、最安全的单例实现方式。

标签: 饿汉式

抱歉,评论功能暂时关闭!