这篇内容主要是自己看完网友写的博客之后的一点点总结。
为什么要用 ?
保证仅有一个实例对象。
单例模式和静态方法区别
- 从面向对象来说,静态方法就和实例对象没有太多的关系,比如工具类;
- 从功能上来说,单例模式可以继承、实现,可以进行有意义的派生。可以保证单个实例对象。
那怎么去实现 ?
第二个问题的答案 ,具体可以看开头的推荐的第二篇博客。这里还需要知道单例模式实现的几个共同点:
- 私有的构造函数,对外无法实例化;
- 由于外部无法实例化,但是还是需要调用呀,那所以要提供给一个能获取单例类的实例对象的方法啊。一般该方法的名字 : createInstance() ;
- createInstance() 返回的值 一般都是私有静态的 。 确保所以调用者调用的都是同一个单例对象嘛。
每种实现方式的优缺点在哪?
这里附上一张自己画的思维图,方便记忆吧。
这里还要补充两点的是:
(1)上述的几种方法中,应该除了枚举类型的方式之外,都可以通过反射或者序列化等方式进行构造。所以,从某个角度来说,也不是单例模式。
正因此,百度知道了对应的文章推荐最佳实践是使用枚举类型 。
那如果我想说,我就不想使用枚举单例模式呢?没办法了么?
哈哈,有人提供了解决办法,看文首的【单例模式那些坑】博客, 不得不佩服都是高手在人间呐~
高能警告: 这种在构造函数里抛出异常的补救办法,只能 针对 饿汉式 !!!
(2)双重校验为什么在synchronized 之后又判null了一次?
假设现有线程A和线程B都去争夺Singleton.class的对象锁,线程A先成功获取锁,线程B被挂起等待锁释放。线程A判断instance为null,然后进行了new ,执行完之后释放了对象锁。这时候线程B拿到了锁,如果这里不进行instance的判null操作,那么线程B又进行一次对象的构造。这样会导致实例除了多个对象哦。
日常推荐哪种方式呢
日常推荐:双重检查模式 、静态内部类模式。
高手过招:枚举单例模式。
单例模式有什么问题么?
要回答这个问题,我们首先回忆一下GC的垃圾回收机制,垃圾回收分为三代,如果类中包含静态成员,垃圾回收机制是不会回收的,也就意味着如果我们无节制的使用单例,会造成程序运行过程中出现大量的实例不会被销毁,会无意识的造成内存使用增高。 如果采用懒加载的方式,在单例未被调用的时候,不会实例化,如果采用饿汉加载的话,那么在程序初始化的时候,就会被初始化,无疑会加重程序的初始化成本,增加启动时间。
单例模式和静态方法各自适合什么场景?
单例模式常用的场景有哪些
- 资源开销大的线程池、数据库连接池等,
- 系统运行时的一些配置和参数。这些配置是公共的,存在于整个生命周期的。如果每次需要就new一个,明显是浪费内存,所以这种也可以使用单例模式