java和kotlin实现单例模式

定义及使用场景

定义:确保某个类只有一个实例,而且自行实例化提供给外部使用。

使用场景:某个类型的对象实例应该有且只有一个,或者避免创建多个对象实例消耗过多的资源时。如:网络库,访问IO,数据库时要考虑单例模式。

单例模式的实现方式

1.饿汉式

优点:简单,线程安全
缺点:在类加载的时候就创建,不管需不需要都会创建,不能传参
适用场景:单例的创建开销小
java:

public class HungrySingleton {
    //在类加载的时候创建单例
    private static HungrySingleton instance = new HungrySingleton();

    //私有化构造方法,避免外部调用
    private HungrySingleton() {
    }

    //对外提供方法题获取单例对象
    public static HungrySingleton getInstance() {
        return instance;
    }

    /**
     * 反序列化也没有问题
     */
    private Object readResolve() {
        return instance;
    }
}

kotlin:

//kotlin中没有static关键字,直接用object声明类就可以
object HungrySingleton {
    fun testXX() {
        Log.e(TAG, "testXX: ")
    }
}
2.懒汉式(线程安全)

优点:需要的时候才创建,可以传参
缺点:为了保证线程安全,getInstance方法是用synchronized修饰的,导致每次调用该方法的时候都会被同步,这样会消耗不必要的资源(不必要的同步开销)。所以这种模式一般不建议使用.

java:

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
    }

    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

kotlin:

class LazySingleton {
    //私有化构造方法
    private constructor() {

    }

    companion object {
        private var instance: LazySingleton? = null

        //对外提供获取单例方法
        @Synchronized
        fun getDefault(): LazySingleton {
            if (instance == null) {
                instance = LazySingleton()
            }
            return instance!!
        }
    }
}
3.DCL(Double-Check-Lock双重校验锁)

对懒汉式进行了优化,只有在第一次实例化的时候才会走第二个分支,才会同步,避免了每次都同步造成的不必要的资源消耗。

优点:第一次执行getInstance方法时才会实例化,资源利用率高,效率高。

缺点:偶尔失效(由于JDK版本问题,在jdk1.5之前会失败)
java:

public class DCLSingleton {
    //volatile关键字:
    private volatile static DCLSingleton instance;

    private DCLSingleton() {
    }

    public static DCLSingleton getInstance() {
        if (instance == null) {
            synchronized (DCLSingleton.class) {
                if (instance == null) {
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }
}

kotlin:

class DCLSingleton {
    private constructor(){
        
    }
    companion object {
        val instance: DCLSingleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            DCLSingleton()
        }
    }
}
4.静态内部类

java:

public class StaticInnerClass {
    private static final String TAG = "StaticInnerClass";
    public static String CLASS_INFO = "1班";

    private StaticInnerClass() {
        Log.e(TAG, "StaticInnerClass: ");
    }

    public static StaticInnerClass getInstance() {
        return Creator.instance;
    }

    /**
     * 静态内部类创建单例
     * JVM机制:当一个类被加载的时候,类的加载过程是线程互斥的
     * 所以其它语言不一定适用
     */
    private static class Creator {
        private static StaticInnerClass instance = new StaticInnerClass();
    }
}

kotlin:

class Singleton{
    
    private constructor(){
        
    }
    companion object {
        val instance = SingletonHolder.holder
    }

    private object SingletonHolder {
        val holder= Singleton()
    }

}

当然还有其它很多实现单例模式的方法,比如利用枚举,容器等。还有一点需要注意的是反射和序列化可以破坏单例的设计目的。
总结:在Android中推荐适用DCL静态内部类来实现单例。

ps:有次面试,面试官问我:最优的单例模式实现方法是什么?我当时不知道。面试官说是静态内部类。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值