Android 设计模式之单例模式

在平常开发过程当中时常须要用到设计模式,可是设计模式有23种,如何将这些设计模式了然于胸而且能在实际开发过程当中应用得驾轻就熟呢?和我一块儿跟着《Android源码设计模式解析与实战》一书边学边应用吧!

设计模式系列文章


今天咱们要讲的是单例模式

定义

确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例git

使用场景

  • 确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源
  • 某个类型的对象只应该有一个

使用例子

  • 应用的Application
  • 图片加载框架对象,好比咱们的ImageLoader,经常使用的图片加载框架Glide,universal-image-loader等
  • 数据请求管理类,好比能够用一个类来统一全部的数据请求处理,访问数据库,网络请求等,这样的类确定只须要一个实例

实现

实现的要点

  • 构造函数不对外开放,必须为Private(就是不能用New的形式生成对象)
  • 经过一个静态方法或者枚举返回单例对象
  • 确保单例类的对象有且只有一个,尤为是在多线程环境下
  • 确保单例类对象在反序列化时不会从新建立对象

常见的实现方式

饿汉单例模式

public class Singleton {
    private static final Singleton singleton = new Singleton();
    //构造函数私有化
    private Singleton() {
    }
    //公有的静态函数,对外暴露获取单例对象的接口
    public static Singleton getInstance() {
        return singleton;
    }
}
复制代码
  • 饿汉单例模式采用的是静态变量 + fianl关键字的方式来确保单例模式,应用启动的时候就生成单例对象,效率不高

懒汉模式

public class Singleton {
    private static Singleton singleton;
    //构造函数私有化
    private Singleton() {
    }
    //公有的静态函数,对外暴露获取单例对象的接口
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}
复制代码
  • 懒汉模式的主要问题在于因为加了synchronized关键字,每调用一次getInstance方法,都会进行同步,形成了没必要要的开销

以上的2种模式用的都很少,了解一下就好,下面介绍平时用得比较多的单例模式github

Double Check Lock(DCL)模式(双重检查锁定模式)

public class Singleton {
    private volatile static Singleton singleton = null;
    //构造函数私有化
    private Singleton() {
    }
    //公有的静态函数,对外暴露获取单例对象的接口
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
复制代码
  • DCL模式是使用最多的单例模式,它不只能保证线程安全,资源利用率高,第一次执行getInstance时单例对象才会实例化;同时,后续调用getInstance方法时又不会有懒汉模式的重复同步的问题,效率更高;在绝大多数状况下都能保证单例对象的惟一性
  • DCL模式须要注意要用volatile关键字,不然仍是会致使建立多个实例
  • DCL模式的缺点是第一次加载时因为须要同步反应会稍慢;在低于JDK1.5的版本里因为Java内存模型的缘由有可能会失效

静态内部类单例模式

public class Singleton {
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        return SingletonHolder.sInstance;
    }
    
    //静态内部类
    private static class SingletonHolder {
        private static final Singleton sInstance = new Singleton();
    }
}
复制代码
  • 第一次加载Singleton类时不会初始化sInstance,只有在第一次调用getInstance方法时才会初始化sInstance,延迟了单例对象的实例化
  • 静态内部类单例模式不只能保证线程安全也能保证单例对象的惟一性

静态内部类单例模式和DCL模式是推荐的单例实现模式数据库

枚举单例

public enum Singleton {
    INSTANCE;
}
复制代码
  • 默认枚举实例的建立是线程安全的,而且在任何状况下它都是一个单例
  • 其余的单例模式,在一种状况下会出现失效的状况——反序列化,可是枚举即便在反序列化状况下也不会失效

总结

  • 单例模式是运用频率很高的模式,因为在客户端通常没有高并发的状况,如今的JDK版本也已经到了9了,通常推荐用DCL模式和静态内部类2种实现。
  • 单例对象的生命周期很长,若是持有Context,很容易引起内存泄漏,因此传递给单例对象的Context最好是Application Context

最后加点福利

  • 单例模式的代码格式都是固定的,每次都要那么写有点麻烦,我们能够用添加模板的方法来偷懒,详情见图。

添加单例模式的模板

  • 添加了模板后,在须要实现单例模式的类里面直接输入你的模板名字,如图中的sin, Android Studio就会出现提示,回车搞定!赶忙试试吧!

源码地址:https://github.com/snowdream1314/DesignPatternsExamples设计模式


欢迎关注个人微信公众号,和我一块儿学习一块儿成长! 安全

AntDream
相关文章
相关标签/搜索