本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Android中的单例模式
单例模式是设计模式最基本的吧,所有的设计模式应该也都是从单例模式开始的吧。
单例模式是我们最基本也是最常用的设计模式,通过单例模式我们可以保证系统中只有一个实例,在不同的地方调用都是这个实例!
下面看看如何使用Java和Kotlin分别定义单例模式吧。
一、饿汉式
在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。并且以后不再改变,其天生是线程安全的。但是缺点是稍微消耗资源。
class Singleton{
private static Singleton _instance = new Singleton();
private Singleton(){}
public static Instance getInstance(){
return _instance;
}
}
Kotlin的实现
object Singleton
是的我们最常用的object单例就是饿汉式的实现
二、懒汉式
懒汉式相比饿汉式的优点和缺点
优点:延迟加载(需要的时候才去加载)
缺点:线程不安全,在多线程中很容易出现不同步的情况
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Kotlin的实现
class Singleton private constructor() {
companion object {
private var instance: Singleton? = null
get() {
if (field == null) {
field = Singleton()
}
return field
}
fun get(): Singleton{
return instance!!
}
}
}
三、加同步锁 + 双重检验锁
由于懒汉式会出现线程不安全的问题,那我们通过加同步锁来保证线程的安全,同时进行双重的判空避免造成不必要的同步开销。
public class Singleton {
private static Singleton instance = null;
private Singleton () {
}
public static Singleton getInstance () {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance ;
}
}
kotlin的实现
class Singleton private constructor() {
companion object {
val instance: Singleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
Singleton()
}
}
}
四、内部类的实现
这种方式相比懒汉式和饿汉式的特点是延迟加载,线程安全,同时也减少了内存消耗。
public class SingletonInner {
private static class SingletonHolder {
private static SingletonInner instance = new SingletonInner();
}
private SingletonInner() {
}
public static SingletonInner getInstance() {
return SingletonHolder.instance;
}
}
Kotlin的实现
class SingletonInner private constructor() {
companion object {
val instance = SingletonHolder.holder
}
private object SingletonHolder {
val holder= SingletonInner()
}
}
总结
以上都是常用的单例定义方式,其实单例的实现还有很多实现的方式,如枚举,容器等,但是都不常用。
由于我们Android客户端并没有太多的并发,多线程等场景,所以大家使用哪一种单例都不会有太大的影响,就像Kotlin推荐使用的object单例一样。
大家只需要注意在多线程中用到单例对象的时候留心即可,是否需要同步锁,可以分不同的场景使用不同的单例定义方式。
注意:
单例模式由于全局只有一个实例,所以如果持有上下文是Activity对象,那么会导致Activity对象无法释放,会造成内存泄露