前言
我不知道大家工作或者面试时候遇到过单例模式没,面试的话我记得我当时在17年第一次实习的时候,就遇到了单例模式,面试官是我后来的leader,当时就让我手写单例,我记得我就写出了饿汉式,懒汉式,但是并没说出懒汉和饿汉的区别,当时他给我一通解释我才知道了其中的奥秘。
写这篇文章之前我刻意的在我手上的项目里面去找了找,我发现单例在每个项目里面都有运用到,而且我后面所说的几种实现还基本上都涉及了,还挺有意思的。
开篇我就给大家一个思考题:为什么不用静态方法而用单例模式?
问题的答案我会在最后公布,大家可以带着问题看下去,看看大家的思考是不是跟我一样的。
大家肯定也能经常听到身边的同学说单例很简单,自己也会,但是真到自己的时候你能就一个知识点讲的很透彻,并且能够发散思考引出更多的答案吗?或者能说出他每种模式更适合的场景么?这是值得深思的。
首先给单例下一个定义:在当前进程中,通过单例模式创建的类有且只有一个实例。
单例有如下几个特点:
- 在Java应用中,单例模式能保证在一个JVM中,该对象只有一个实例存在
- 构造器必须是私有的,外部类无法通过调用构造器方法创建该实例
- 没有公开的set方法,外部类无法调用set方法创建该实例
- 提供一个公开的get方法获取唯一的这个实例
那单例模式有什么好处呢?
- 某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销
- 省去了new操作符,降低了系统内存的使用频率,减轻GC压力
- 系统中某些类,如spring里的controller,控制着处理流程,如果该类可以创建多个的话,系统完全乱了
- 避免了对资源的重复占用
好了,单例模式的定义也清楚了,好处也了解了,先看一个饿汉式的写法
饿汉式
public class Singleton { // 创建一个实例对象 private static Singleton instance = new Singleton(); /** * 私有构造方法,防止被实例化 */ private Singleton(){} /** * 静态get方法 */ public static Singlet<strong>本文来源gaodai#ma#com搞@@代~&码*网2</strong>on getInstance(){ return instance; } }
之所以叫饿汉式大家可以理解为他饿,他想提前把对象new出来,这样别人哪怕是第一次获取这个类对象的时候直接就存在这个类了,省去了创建类这一步的开销。
等我介绍完懒汉之后,对比一下大家就知道两者的区别,以及各自适用在什么场景了。
懒汉式
线程不安全的模式
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }