单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
核心特点
-
唯一性:一个类只能有一个实例
-
全局访问:提供全局访问该实例的方式
-
延迟初始化:通常在第一次被请求时才创建实例(可选)
实现方式(Java示例)
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;}
}
优点:线程安全,性能较好(只有第一次创建时需要同步)
5. 静态内部类实现(推荐方式)
public class Singleton {private Singleton() {}private static class Holder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return Holder.INSTANCE;}
}
优点:线程安全,延迟加载,实现简单
6. 枚举实现(最佳方式,Java 1.5+)
public enum Singleton {INSTANCE;public void doSomething() {// 业务方法}
}
优点:线程安全,防止反射攻击,防止反序列化重新创建对象
缺点:不够灵活(不能延迟初始化)
应用场景
-
配置管理:全局配置对象
-
日志记录器:应用只需要一个日志记录器实例
-
数据库连接池:避免频繁创建和销毁连接
-
线程池:管理应用中的线程资源
-
缓存系统:全局缓存访问点
注意事项
-
多线程环境:确保线程安全
-
序列化:如果需要序列化,应实现
readResolve()
方法防止反序列化创建新实例 -
反射攻击:可以通过反射调用私有构造函数,需要额外防护
-
单元测试:单例可能使测试变得困难(难以模拟替代)
-
全局状态:过度使用单例可能导致代码耦合度高
单例模式是设计模式中最简单但也是最容易误用的模式之一,应谨慎使用,避免滥用。