Java设计模式之单例模式详解


什么是单例模式?

单例模式(Singleton Pattern)是最简单的设计模式之一,它保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式属于创建型模式。

为什么使用单例模式?

  • 确保某个类只有一个实例
  • 提供对该实例的全局访问点
  • 控制共享资源的访问

单例模式的实现方式

1. 懒汉式(线程不安全)

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

这种方式是最基本的实现方式,但它不是线程安全的。

2. 懒汉式(线程安全)

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

通过synchronized关键字实现线程安全,但效率较低。

3. 双重检查锁定(DCL)

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

这种方式既保证了线程安全,又提高了效率。

4. 饿汉式

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

这种方式是线程安全的,但会在类加载时就初始化实例。

5. 静态内部类

public class Singleton {
    private Singleton() {}
    
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

这是推荐的实现方式,既保证了线程安全,又实现了懒加载。

使用场景

  1. 配置管理器
  2. 数据库连接池
  3. 线程池
  4. 日志管理器
  5. 缓存管理器

注意事项

  1. 构造函数必须是私有的
  2. 考虑线程安全问题
  3. 注意序列化和反序列化问题
  4. 防止反射攻击

总结

单例模式虽然简单,但实现时需要考虑多种因素。在实际开发中,建议使用静态内部类或枚举方式来实现单例模式,它们能够保证线程安全,并且实现简单。

代码示例:实际应用中的单例模式

// 配置管理器示例
public class ConfigManager {
    private static volatile ConfigManager instance;
    private Properties properties;
    
    private ConfigManager() {
        properties = new Properties();
        try {
            properties.load(new FileInputStream("config.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static ConfigManager getInstance() {
        if (instance == null) {
            synchronized (ConfigManager.class) {
                if (instance == null) {
                    instance = new ConfigManager();
                }
            }
        }
        return instance;
    }
    
    public String getProperty(String key) {
        return properties.getProperty(key);
    }
}

参考资料

  • 《设计模式:可复用面向对象软件的基础》
  • 《Effective Java》第三版
  • Java API 文档

希望这篇文章能帮助您更好地理解Java中的单例模式。如果您有任何问题,欢迎在评论区讨论!


文章作者: lucky845
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 lucky845 !
评论
  目录