Skip to content

singleton

约 555 字大约 2 分钟

2025-04-21

1. 核心思想

  • 保证一个类仅有一个实例,并提供一个访问它的全局访问点
  • 构造函数私有化,禁止外部直接创建对象
  • 提供一个静态方法获取唯一实例
  • 确保线程安全(在多线程环境下)

2. 适用场景

  • 需要频繁实例化然后销毁的对象
  • 创建对象时耗时过多或耗费资源过多,但又经常用到的对象
  • 系统只需要一个实例对象,如系统配置信息类
  • 需要频繁访问数据库或文件的对象

3. 优缺点分析

优点:

  • 内存中只有一个实例,减少了内存开销
  • 避免对资源的多重占用
  • 提供了对唯一实例的全局访问点
  • 实例的创建时机可控

缺点:

  • 单例模式一般没有接口,扩展困难
  • 单例类的职责过重,在一定程度上违背了单一职责原则
  • 滥用单例可能造成模块间的强耦合
  • 单例模式的测试可能比较困难

4. 实践示例

// 懒汉式(线程安全)
public class Singleton {
    // 私有构造函数
    private Singleton() {}
    
    // 私有静态实例
    private static volatile 
    Singleton instance;
    
    // 公共静态获取方法
    public static Singleton 
    getInstance() {
        if (instance == null) {
            synchronized 
            (Singleton.class) {
                if (instance == 
                null) {
                    instance = new 
                    Singleton();
                }
            }
        }
        return instance;
    }
}

// 饿汉式
public class EagerSingleton {
    // 私有构造函数
    private EagerSingleton() {}
    
    // 在类加载时就创建实例
    private static final 
    EagerSingleton instance = new 
    EagerSingleton();
    
    // 公共静态获取方法
    public static EagerSingleton 
    getInstance() {
        return instance;
    }
}

// 使用示例
public class SingletonDemo {
    public void demo() {
        // 获取单例实例
        Singleton singleton1 = 
        Singleton.getInstance();
        Singleton singleton2 = 
        Singleton.getInstance();
        
        // 验证是否是同一个实例
        System.out.println
        (singleton1 == 
        singleton2);  // 输出:true
    }
}

5. 实践建议

  • 在确实需要单例的场景下才使用单例模式
  • 注意线程安全问题,选择合适的实现方式
  • 考虑使用枚举实现单例,可以防止反序列化重新创建新的对象
  • 注意单例类的职责单一,不要让单例类负责太多功能
  • 考虑到单例类的可测试性,可以为其设计接口或抽象类

贡献者