【设计模式】之单例模式中的饿汉模式和懒汉模式

本文内容:什么是单例模式单例的作用饿汉模式懒汉模式的安全与非安全的实现饿汉模式与懒汉模式的区别.

什么是单例模式?

单例模式:保证一个类,仅有一个实例。提供一个访问它的全局访问点。

单例的作用?

让某个类,仅有一个实例对象。

为什么Retrofit要使用单例模式?
倘若不做单例,它会产生多个对象,反复实例化造成资源浪费。就App来说,一个App里有多少个网络请求,80%几乎需要调用同一个Retrofit对象,大量的实例化操作,这光是想一想都足以让人虎躯一震了。也就是说,如果只是两三个的对象使用,Retrofit没必要使用单例。

饿汉模式是什么?

饿汉模式:是无论你用不用这个对象,在类加载的时候就已经把这个对象实例化好了。

Java实现方式

public class HungrySingle {

    //类加载时就进行实例化对象。
    private static HungrySingle hungrySingle=new HungrySingle();

    //设为private,不让外部代码对其进行new实例化对象。
    private HungrySingle() {
    }

    public static HungrySingle getInstance(){
        return hungrySingle;
    }
    
}

kotlin实现方式:

object HungrySingle

相信你已经被kotlin实现单例(饿汉模式)的简洁度吓到,再次感叹kt大法好。

懒汉模式是什么?

懒汉模式: 需要用这个对象的时候,才会去实例化该对象。

Java实现

public class LazySingleJava {
    private static LazySingleJava lazySingleJava;
    public LazySingleJava() {}
    
    public static LazySingleJava getInstance(){
        if (lazySingleJava==null){
            lazySingleJava=new LazySingleJava();
        }
        return lazySingleJava;
    }
}

kotlin实现

Tips:

  • 这里注意不要用return lazySingle!! 代码,它代表肯定不为空。如果lazySingle真的为空,这样写则会抛异常,导致程序crash;
  • 用LazySingle?则让kotlin做了处理,就算为空也不会crash掉程序。
class LazySingle private constructor(){

    companion object{
        private var lazySingle:LazySingle?=null
        get(){
            if(lazySingle==null){
                lazySingle=LazySingle()
            }
            return lazySingle
        }

        fun getInstane(): LazySingle? {
            return lazySingle
        }
    }
}

‘安全’的懒汉模式(线程安全)

情景描述:线程A调用全局访问点getInstance( ),这是对象为null,这时线程A莫名阻塞了。这是我们线程B又去调用全局访问点getInstance( ),这时对象仍然为null,它去创建了新的对象,这时线程A又运行,又去创建了一个对象。

结果:这时所谓的‘单例’则创建了多个对象,违反了我们的单例模式。

安全的懒汉模式

缺点:因在全局访问点上加了同步锁,速度慢;无论是否已有实例化对象,都会走一次锁。

  • Java实现
public class LazySingleJava {
    private static LazySingleJava lazySingleJava;
    public LazySingleJava() { }

    //这里增加同步锁synchronized,保证同一时间,只有一个线程来操作它。
    public static synchronized LazySingleJava getInstance(){
        if (lazySingleJava==null){
            lazySingleJava=new LazySingleJava();
        }
        return lazySingleJava;
    }
}
  • kotlin实现
class LazySingle private constructor(){

    companion object{
        private var lazySingle:LazySingle?=null
        get(){
            if(lazySingle==null){
                lazySingle=LazySingle()
            }
            return lazySingle
        }
        
        //增加@Synchronized注解
        @Synchronized
        fun getInstane(): LazySingle? {
            return lazySingle
        }
    }
}
安全且高效的懒汉模式(双重校验锁)

优点:速度提升;若实例已存在,则不存在违反单例设计的问题,可以直接获取对象,减少因为加锁造成的速度问题。

  • Java实现
public class LazySingleJava {
    private static LazySingleJava lazySingleJava;
    public LazySingleJava() { }

    public static  LazySingleJava getInstance(){
        if (lazySingleJava==null){
            //将 synchronized 放置于这里
            synchronized(LazySingleJava.class){
                lazySingleJava=new LazySingleJava();
            }
        }
        return lazySingleJava;
    }
}
  • kotlin实现
class LazySingle private constructor(){
    companion object{
        val instance:LazySingle by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED){
            LazySingle()
        }
    }
}

饿汉模式与懒汉模式的安全以及性能的区别?

线程安全

  • 饿汉模式在线程还未出现的时候就已经实例化了,所以饿汉是线程安全的。

效率

  • 饿汉模式没有加任何的锁,执行效率高于懒汉模式。

内存

  • 饿汉模式在类加载时就实例化了,不管是否调用。相对来说,饿汉会消耗内存一些。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值