1、定义
单例对象的类必须保证只有一个实例存在。
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2、使用场景
避免产生对个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。
3、实现方式
- 饿汉模式
public class CEO {
private static final CEO mCEO = new CEO();
private CEO() {
}
public static CEO getCEO() {
return mCEO;
}
}
- 懒汉模式
public class CEO {
private static CEO instance;
private CEO() {
}
public synchronized static CEO getCEO() {
if (instance == null) {
instance = new CEO();
}
return instance;
}
}
- 懒汉模式 - double checkLock
public class CEO {
private CEO() {
}
private static CEO instance = null;
public static CEO getInstance() {
//避免不必要的同步
if (instance == null) {
synchronized (CEO.class) {
//同步后仍然为null,再创建
if (instance == null) {
instance = new CEO();
}
}
}
return instance;
}
}
- 静态内部类
public class CEO {
private CEO() {
}
public static CEO getInstance() {
return CEOHolder.instance;
}
/**
* 静态内部类
* 确保线程安全,也能保证单例对象的唯一性
* 延时了单例的初始化
*/
private static class CEOHolder {
private static final CEO instance = new CEO();
}
//防止反序列化时,可以通过反射来创建新对象
private Object readResolve() throws ObjectStreamException {
return getInstance();
}
}
- 枚举
默认枚举实例的创建是线程安全的,并且在任何情况下它都是一个单例,包括反序列化的时候(其余的实现都会在反序列化时出现问题,静态内部类实现方式已给出解决方案 反序列化相关)
public enum CEO {
INSTANCE;
}
- 容器
通过统一的接口进行获取操作,降低了使用成本,及耦合度
public class SingletonManager {
private static Map<String, Object> sObjectMap = new HashMap<>();
private SingletonManager() {
}
public static void registerService(String key, Object instance) {
if (!sObjectMap.containsKey(key)) {
sObjectMap.put(key, instance);
}
}
public static Object getService(String key) {
return sObjectMap.get(key);
}
}
4、Demo
5、Android 源码中的运用
android.content.Context
public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass)
优缺点
- 优点
- 减少了内存开支
- 减少了系统的性能开销
- 避免对资源的多重占用
- 可以在系统设置全局的访问点,优化和共享资源访问
- 缺点
- 单例模式一般没有接口,扩展性差
- 单例对象如果持有 Context 对象,容易引发内存泄漏,最好使用 Application Context
网友评论