单例模式
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一的实例。这种模式在需要控制资源共享的应用场景中非常有用,例如数据库连接、日志记录器等。
特点:
- 唯一性:在整个应用程序生命周期内,某个类只会有一个实例存在。
- 全局访问点:提供了一个静态方法来获取该类的唯一实例。
创建:
- 私有化构造方法,无法被 new 创建对象
- 类中定义公共方法获取对象
使用场景
示例与说明 | |
---|---|
资源共享 | 当需要管理共享资源时,如数据库连接池、线程池等,保证系统中只有一个实例来控制对这些资源的访问。 例如: DatabaseManager.getInstance() 。 |
配置设置 | 应用程序中的配置参数通常在整个应用生命周期内保持不变且需要被频繁访问,使用单例可以避免重复加载配置。 例如: AppConfig.getInstance().getProperty("key") 。 |
日志记录器 | 日志记录是典型的单例应用场景,整个应用程序只需要一个日志记录器实例,这样可以保证所有日志信息都被集中管理和输出。 例如: Logger.getLogger("MyLogger") 。 |
管理器或控制器对象 | 管理应用程序状态或行为的控制器对象,如设备管理器、窗口管理器等,确保只有一个实例存在以维护一致的状态。 例如: DeviceManager.getInstance().addDevice(device) 。 |
缓存机制 | 缓存数据的对象,如内存缓存,通常需要在整个应用程序中共享并保持一致性,单例模式有助于实现这一点。 例如: CacheManager.getInstance().getCachedData("key") 。 |
工厂类 | 工厂类用于生成其他对象,如果整个系统只需要一个这样的工厂,则适合使用单例模式。 例如: ObjectFactory.getInstance().createObject(type) 。 |
防止多个实例导致的错误 | 某些情况下,多实例可能会导致逻辑错误或数据不一致的问题,比如计数器、锁等。 例如: Counter.getInstance().increment() 。 |
实现方式 | 线程安全 | 反射安全 | 序列化安全 | 懒加载 | 推荐程度 |
---|---|---|---|---|---|
饿汉式 | ✅ | ❌ | ❌ | ❌ | ⭐⭐⭐ |
懒汉式 | ❌ | ❌ | ❌ | ✅ | ⭐⭐ |
双重检查锁定 | ✅ | ❌ | ❌ | ✅ | ⭐⭐⭐⭐ |
静态内部类 | ✅ | ❌ | ❌ | ✅ | ⭐⭐⭐⭐ |
枚举单例 | ✅ | ✅ | ✅ | ❌ | ⭐⭐⭐⭐⭐ |
示例:
饿汉式:
特点:
实现简单且线程安全,在类加载时实例化对象。但如果该实例占用较多资源而未被使用,则会造成浪费。
java
public class SingletonEHan {
private static final SingletonEHan INSTANCE = new SingletonEHan();
private SingletonEHan (){
}
public static SingletonEHan getInstance() {
return INSTANCE;
}
}
// 使用
SingletonEHan instance = SingletonEHan.getInstance();
懒汉式:
特点:
在使用时加载时实例化对象,但非线程安全需要使用锁来确保实例的唯一性
java
public class SingletonLanHan {
private static SingletonLanHan instance = null;
private SingletonLanHan(){}
public static SingletonLanHan getInstance(){
if(instance == null){
synchronized(SingletonLanHan.class){
if (instance == null){
instance = new SingletonLanHan();
}
}
}
return instance;
}
}
// 使用
SingletonLanHan instance = SingletonLanHan.getInstance();
内部类:
特点:避免了线程不安全,并且可以延迟加载
java
public class SingletonIn {
private SingletonIn() {
}
private static class SingletonHolder {
private static final SingletonIn INSTANCE = new SingletonIn();
}
public static SingletonIn getInstance() {
return SingletonHolder.INSTANCE;
}
}
// 使用
SingletonIn instance = SingletonIn.getInstance();
枚举(推荐):
特点:
实现简单,线程安全,防止反序列化破坏单例,防止反射攻击
java
public enum SingletonEnum {
INSTANCE;
/**
* 可以添加方法和属性
*/
public void doSomething() {
System.out.println("执行单例的方法");
}
}
// 使用
SingletonEnum.INSTANCE.doSomething();