单例模式是使用最广的设计模式,也是大家最为熟知的.
该系列其他文章:
- 安卓设计模式(一)面向对象六大设计原则
- 安卓设计模式(二)单例模式
- 安卓设计模式(三)Builder模式
- 安卓设计模式(四)装饰者模式
- 安卓设计模式(五)代理模式
- 安卓设计模式(六)策略模式
- 安卓设计模式(七)模板方法模式
- 安卓设计模式(八)工厂方法模式
单例模式的使用场景
- 该类会占用较多的资源,如线程资源,IO操作,网络请求等
- 该类的数据应该是全局的,共享的
- 该类的实例生命周期应该是全局的,在appliction的整个声明周期可能都需要用到
单例模式的具体写法
- 恶汉式单例
恶汉式由于类加载时就创建好了对象,不存在线程安全和效率问题,缺点是过早的创建对象,并且不能在初始化时传参
public class Singleton {
private static final Singleton sSingleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return sSingleton;
}
}
- Double Check Lock实现单例
这种是目前使用最广泛的单例,线程安全,并且效率不低,我一般使用这种
public class Singleton {
private volatile static Singleton sSingleton=null;
private Singleton() {
}
public static Singleton getInstance() {
if (sSingleton == null)
synchronized (Singleton.class) {
if (sSingleton == null)
sSingleton = new Singleton();
}
return sSingleton;
}
}
注意到使用了volatile关键字修饰单例对象,这样可以保证sSingleton对象每次都是从主内存中读取,从而避免在创建对象时由于Java内存模型带来的不必要的问题.
- 静态内部类单例
这种也是比较好的单例,线程安全,保证唯一,延迟实例化统统都具有.
使用到java内部类的加载时机,只有在内部类的静态成员被调用时才会去加载静态内部类,所以同样是延迟加载
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.sSingleton;
}
private static class SingletonHolder {
private static final Singleton sSingleton = new Singleton();
}
}
- 枚举单例
利用到枚举的特性,在任何情况下,枚举默认就是单一实例,枚举的创建默认就是线程安全的.并且枚举跟普通类一样,可以拥有属性和方法.
public enum SingletonEnum {
SINGLETON_ENUM;
public void doSth() {
}
}
- 使用容器实现单例
这种单例管理方式在Android源码中有用到,在单例比较多的时候,采用容器来管理和获取单例是非常好的方式.在程序初始化时注入相应的单例,任何时候使用容器来获取单例.
public class SingletonManager {
private static Map<String, Object> objectMap = new HashMap<String, Object>();
private SingletonManager() {
}
public static void registerService(String key, Object instance) {//存入
if (objectMap.containsKey(key)) {
objectMap.put(key, instance);
}
}
public static Object getService(String key) {//获取
return objectMap.get(key);
}
}
最后
以上五种是比较好的单例实现方式,均可保证线程安全,效率高,延迟实例化(恶汉式除外),我推荐使用DCL方式的单例
关于作者
- 简 书:uncochen
- github:ChenZhen
- 新浪微博:@Chen丶振
- Email:18620156376@163.com
网友评论