大家好,我是听者,耳听心受的听,孙行者的者,感谢大家阅读我的文章。
今天给大家带来的是android单例模式的介绍,单例模式是程序员最早接触的也是最熟悉的设计模式,单例是确保系统中某个类只有一个实例。单例模式为了解决频繁的生成对
象而消耗太多的资源,比如网络请就、加载图片、读取数据库等等,还有就是系统中某些类必须只有一个对象,比如用户信息等我们就可以做成单例。
单例的实现方式基本上有饿汉模式、懒汉模式、DCL、静态内部类、枚举、容器六种实现方式,下面我们先逐一看一下实现方式,再给大家说说每一个的优缺点。
饿汉模式:
public class HungrySingleton {
//在类加载的时候就已经加载出来,不管用不用
private static HungrySingleton mInstance = new HungrySingleton();
private HungrySingleton() {
// 构造方法私有化
}
public static HungrySingleton getInstance() {
return mInstance;
}
}
// 懒汉模式
public class LazySingleton {
private static LazySingleton mInstance;
private LazySingleton() {
// 构造方法私有化
}
// 线程同步锁,在使用的时候初始化
public static synchronized LazySingleton getInstance() {
if (null == mInstance) {
mInstance = new LazySingleton();
}
return mInstance;
}
}
// DCL(双锁模式)
public static DCLSingleton {
private static DCLSingleton mInstance;
private DCLSingleton() {
// 构造方法私有化
}
public static DCLSingleton getInstance() {
if (null == mInstance) {// 不是每次get的时候都线程同步
synchronized (DCLSingleton.class) {
if (null == mInstance) {
mInstance = new DCLSingleton();
}
}
}
return mInstance;
}
}
// 静态内部类
public static class InnerClassSingleton {
private static class InnerClass {
public static final InnerClassSingleton mInstance = new InnerClassSingleton();
}
private InnerClassSingleton() {
// 构造方法私有
}
public static InnerClassSingleton getInstance() {
return InnerClass.mInstance;
}
}
// 枚举
public enum EnumSingleton {
mInstance;
public static EnumSingleton getInstance() {
return mInstance;
}
}
// 容器
public static class SingletonManager {
private final static Map<String, Object> mServices = new HashMap<>();
private SingletonManager() {
}
public static void registerService(String key, Object service) {
if (!mServices.containsKey(key)) {
mServices.put(key, service);
}
}
public static Object getService(String key) {
Object object = mServices.get(key);
if (null == object) {
throw new IllegalArgumentException("this service didn't register");
}
return object;
}
}
好的,今天就介绍到这里,如果有什么疑问,欢迎加入 Android高级开发交流群 群号: 474440973,听者在北京等你!
从上面单例的实现总结,实现一个单例构造方法必须私有,有一个获取单例的静态方法,保证线程安全。构造方法私有、静态方法获取单例每种实现方法都一样,下面我们比较线程安全和效率、内存问题。
饿汉模式,在加载类的时候就把单例对象加载进来,不存在线程安全的问题,但是不管用不用都会把单例对象加载进内存,并且还不能回收,导致浪费内存资源。
懒汉模式,通过线程同步锁,在get的时候判断存在不存在,不存在再创建,虽然解决了内存资源浪费的问题,但是每次get的时候都会加同步锁,降低了程序的执行效率。
DCL模式,通过两次判null实现线程同步和在使用时加载单例对象,既完成了线程同步又节约了内存,但是基于重排序等考虑,这种方法在极其小的概率会出现问题,这里就深入讲解了,大家知道有这么一回事就ok。
静态内部类:静态内部类在使用的时候加载,这样既保证了线程安全也保证实例的唯一,还讲单例实例延迟加载了。(推荐使用这种方式)
枚举模式:大家都知道枚举是线程安全的,并且可以调用其方法,保证生成唯一的实例。
容器模式:通过一个单例管理器将单例保存在一个Map中,这样不仅保证了实例的唯一性还能更好的维护管理单例模式。
单例模式不仅可以减少内存开销而且可以提高效率,也可以避免多重占用资源,也能共享资源,但是单例一般没有接口,很难扩展,而且单例使用上下文时一定要使用Application不然会导致内存泄漏。