【Android】设计模式之单例模式

00、前言

设计模式,不仅面试官爱问,而且在做一些架构上的设计,或者一些库的封装上,也是必不可少的要素。那么今天我们来捋一捋最常见,也最容易理解的设计模式——单例模式。

01、单例模式

基础写法

想起,当年为了应付面试。便把下面的单例模式的写法强行记忆了下来。

public class Singleton(){
    private static Singleton instance;
    private static Singleton getInstance(){
        if(instance == null){
           instance = new Singleton;
        }
         return instance;
    }

简单分析一下上面的写法。首先定义一个静态变量,提供一个静态方法实例化,并将实例赋值给静态变量,最后将该实例作为该函数的返回值,就完事了。

逻辑上也很好理解,就是当调用 getInstance(),如果 instance 为空,则新建一个,否则返回实例。

但单例模式,远远不仅如此。还有很多情况与写法。

单例模式多种写法

首先,思考一下为什么要用单例模式。单例模式,就是设计者,希望这个类只被实例化一次,就可以提供给全局使用。
那么怎么才能保证【只被实例化一次】呢?那当然是把,构造器私有化, 这样别人就不能去实例化我们设计的类了。

但是,在实际项目中,还需要考虑多线程的问题。像上面那种写法,是无法保证线程安全的。上面那种模式,我们成为懒汉模式。为什么叫懒汉模式呢?也很好理解,因为懒嘛,所以就等到要用的时候,才进行实例化。

至于这种模式为什么不是线程安全的呢?那是因为当两个线程同时走到 if(instance == null) 的时候,条件都是成立的,这时候,第一个拿到的实例,和第二个拿到的实例就不是同一个实例了。这样违背了,我们设计单例的初衷。

懒汉-线程安全

那么可能有人会想到,在原本的基础上加上同步锁 synchronized 。于是就有了 懒汉-线程安全 的单例模式。

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

双重检查加锁

因为同步锁的加解锁操作会耗时,这样会降低效率。于是在上面的基础上出现了 双重检查加锁 的单例模式。

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

在加锁前,先进行判断,这样就避免不必要的加解锁操作,从而提供效率了~

饿汉模式

解决多线程,除了上面加锁的思路。还有一种思路就是在写单例模式的类的时候,就已经初始化好了,无需等用户调用的时候再初始化,也是一条思路。于是就有了饿汉模式。因为饿嘛,就是等不及了。先把“吃的”(实例)准备好先。

public class Singleton(){
    private static Singleton instance =  new Singleton()
    private static Singleton getInstance(){
        return instance;
    }
}

静态内部类单例模式

这种模式存在一个问题,就是在类被加载的时候,就要完成初始化。所以这会导致加载缓慢。为了解决这个问题-于是有了 静态内部类单例模式

public class Singleton(){
    private Singleton()
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
    private static class SingletonHolder{
        private static final Singleton instance = new Singleton();
    }
}

02、图总结

有点凌乱?没事,上图。

记住它们出现的原因,为了解决什么样的问题。就可以记住它们了。

03、kotlin 写法

接下来,就是看看 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!!
            }
    }
}

//private constructor() 主构造器私有化,并自定义属性访问器 fun get():Singleton

懒汉-线程安全模式

class Singleton private constructor() {
    companion object {
        private var instance: SingletonDemo? = null
            get() {
                if (field == null) {
                    field = Singleton()
                }
                return field
            }

        @Synchronized
        fun get(): SingletonDemo {
            return instance!!
        }
    }

// 在get()方法上添加了 @Synchronized 注解。

双重检查加锁模式

class Singleton private constructor() {
    companion object {
        val instance: Singleton by 
            lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Singleton()
        }
    }
}

//lazy 是kotlin中的延迟属性

饿汉模式

object Singleton

静态内部类模式

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

    private object SingletonHolder {
        val holder = Singleton ()
    }

}

作者:Quincy_Ye
链接:https://juejin.cn/post/7151584359110639653
更多Android学习笔记+视频资料可点击文末卡片获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值