什么是单例模式?
单例模式是设计模式中最简单也最常用的一种,今天来聊聊。
什么是单例
单例就是一个类只有一个实例。
不管你获取多少次,拿到的都是同一个对象。
为什么需要单例
节省资源
有些对象创建起来很耗资源,比如数据库连接池、线程池。
没必要创建多个,一个就够用了。
保持一致性
有些对象需要全局唯一,比如配置管理器、日志管理器。
如果有多个实例,可能导致数据不一致。
单例的写法
懒汉式
第一次使用的时候才创建。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式
类加载的时候就创建。
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
双重检查锁
懒汉式的改进,减少锁的开销。
public class Singleton {
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 Holder {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return Holder.instance;
}
}
在Spring中的单例
Spring的Bean默认就是单例的。
@Service
public class UserService {
// 默认单例,整个应用只有一个UserService实例
}
大部分情况下你不需要自己写单例,用Spring管理就行。
单例的问题
1. 难以测试
单例是全局状态,测试时可能互相影响。
2. 隐藏依赖
代码里直接调用getInstance(),依赖关系不明显。
3. 不利于扩展
以后如果需要多个实例,改起来很麻烦。
最后
单例是面试常考的设计模式,至少要会写几种实现方式。
实际工作中,大部分单例的需求用Spring的Bean就能解决,不需要自己写。
