本文共 3371 字,大约阅读时间需要 11 分钟。
目录
可能你认为的单例模式是这样的
public class Singleton(){ private static Singleton instance; private static Singleton getInstance(){ if(instance==null){ instance = new Singleton; } return instance; }}
定义一个静态变量,提供一个静态方法实例化,并将实例赋值给静态变量,最后将该实例作为该函数的返回值。就完事了。
学过Koltin的同学,这时带着轻佻地语气进入了直播间,呼:“让开,这算啥。麻烦!” 于是在评论区打出了
object Singleton
WoW,只见直播间其他的同学,在公屏上打出了:“666”
上面这是你认为的单例模式吗?是的,它们的确都是单例模式,但,这只是管中窥豹。接下来,我们来一探究竟吧。
其实单例模式,就是设计者,希望这个类只被实例化一次,就可以提供给全局使用。
那么怎么才能保证【只被实例化一次】呢?那当然是把,构造器私有化,这样别人就不能去实例化我们设计的类了。
但是,在实际项目中,需要的考虑更多的东西。
最主要考虑的是:在多线程中,上面那样的实现方式-懒汉模式(懒,就是等到是在要用了,才实例化。所以叫懒汉模式),还能确保是单例了吗?
当然是不可以的,当两个线程同时走到 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(); }}
有点凌乱?没事,上图。
记住他们之间的关系,就能记住有哪些,并且理解为什么有这些了。
接下来,就是看看 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 () }}
PS:秉持着联机学习 1+1>2的原则,欢迎大家指点批评,互相交流学习~
转载地址:http://rlnez.baihongyu.com/