1. 饿汉式
线程安全,调用效率高,但是不能延时加载):
//Java实现
public class A {
private static A instance = new A();
private A(){
}
public static A getInstance(){
return instance;
}
}
//Kotlin实现
object A
一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式。但是问题也比较明显。单例在还没有使用到的时候,初始化就已经完成了。也就是说,如果程序从头到位都没用使用这个单例的话,单例的对象还是会创建。这就造成了不必要的资源浪费。所以不推荐这种实现方式。
2. 懒汉式
2.1 线程不安全
//Java实现
public class B{
private static B instance;
private B(){}
public static B getInstance(){
if(instance==null){
instance=new B();
}
return instance;
}
}
//Kotlin实现
class B private constructor() {
companion object {
private var instance: B? = null
get() {
if (field == null) {
field = B()
}
return field
}
fun get(): B{
//不能用getInstance作为为方法名,是因为在伴生对象声明时,内部已有getInstance方法,所以只能取其它名字
return instance!!
}
}
}
2.2 线程安全
//Java实现
public class B{
private static B instance;
private B(){}
public static synchronized B getInstance(){
if(instance==null){
instance=new B();
}
return instance;
}
}
//Kotlin实现
class B private constructor() {
companion object {
private var instance: B? = null
get() {
if (field == null) {
field = B()
}
return field
}
@Synchronized
fun get(): B{
//不能用getInstance作为为方法名,是因为在伴生对象声明时,内部已有getInstance方法,所以只能取其它名字
return instance!!
}
}
}
大家都知道在使用懒汉式会出现线程安全的问题,需要使用使用同步锁,在Kotlin中,如果你需要将方法声明为同步,需要添加@Synchronized注解。
3.Double Check Lock实现单例
DCL也就是双重锁判断机制:
public class C {
private volatile static C instance;
private C (){}
public static C getInstance(){
if(instance==null){
synchronized (C.class){
if(instance==null){
instance=new C();
}
}
}
return instance;
}
}
//kotlin实现
class C private constructor() {
companion object {
val instance: C by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
C()
}
}
}
4. 静态内部类式
//Java实现
public class D{
private static class SingletonHolder{
private static D instance=new D();
}
private D(){
}
public static D getInstance(){
return SingletonHolder.instance;
}
}
//kotlin实现
class D private constructor() {
companion object {
val instance = D.holder
}
private object SingletonHolder {
val holder= D()
}
}
5.枚举类
线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用
public enum E{
INSTANCE(0xFF0000)
private int rgb;
E(int rgb){
this.rgb = rg
}
}
// 调用方法
E.INSTANCE
enum class E(val rgb: Int) {
INSTANCE(0xFF0000)
}
// 调用方法
SingletonDemo.INSTANCE
如何选用:
-
单例对象 占用资源少,不需要延时加载,枚举 好于 饿汉
-
单例对象 占用资源多,需要延时加载,静态内部类 好于 懒汉式
推荐文章:
Kotlin下的5种单例模式 :https://www.jianshu.com/p/5797b3d0ebd0
拥抱kotlin:利用kotlin实现单例模式 :https://www.jianshu.com/p/cc77e78bd0eb
Kotlin学习笔记:Kotlin中五种单例模式的实现 : https://www.jianshu.com/p/677d2a6e1b71