为什么需要设计模式
相信大家在看招聘信息的时候都会看到下面一则内容:
熟悉JAVAEE设计模式,为什么公司都注重设计模式?因为熟练设计模式的同学们可以写出复用性和逻辑性非常强的代码。就像我叫你写一个MySQL的分页操作,你今天就做完了,这很好,如果明天我叫你叫你弄一个Oracle的分页操作,你不就又要重新把一些可复用的代码又写一遍?学过设计模式的同学就可以通过工厂模式和策略模式搭配组合,让客户端决定实例化哪一种数据库,而他们自己只需要写不同数据库对应的逻辑就可以了。
所以设计模式存在的最主要原因是实现高内聚低耦合,一个精通设计模式的程序员可以写出非常美丽的代码,这种程序员哪个公司不想要啊。
接下来进入正题啦,今天我们来学习一下单例模式
什么是单例模式?
单例模式说白了,其实就是在程序的生命周期中只有一个实例对象,其他类不能通过new的方式来实例化对象。例如我有个User类,用了单例模式后,其他类是无法new User()。为人熟知的Spring框架就是单例模式。
那么,单例模式有什么好处呢?
- 能够避免重复创建对象,减少内存消耗
- 避免对资源的多重占用(这个是我上网找的哈哈)
如何实现单例模式?
实现单例模式,我一般都是这三种:
- 饿汉模式
- 懒汉模式
- 双重校验
饿汉模式
饿汉模式其实就是在类加载的时候就实例化对象,这种方式是比较粗暴,但是浪费内存,容易产生垃圾对象,代码实现如下:
public class Singleton {
// 在类加载时实例化(饿汉模式)
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
懒汉模式
懒汉模式就是所谓的懒加载,当调用的时候才会进行实例化,看代码:
public class Singleton {
// 在调用时实例化(懒汉模式)
private static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(Objects.isNull(singleton)){
singleton = new Singleton();
}
return singleton;
}
}
如代码所示,在调用getInstance()方法时才进行实例化,成功解决了饿汉模式留下的问题–浪费内存。
但有个问题,在并发环境下,如果多个线程同时调用getInstance(),那就不是会创建多个Singleton对象?为此我们引出双重校验,算是对懒汉模式的一种升级。
双重校验
双重校验其实就是对懒汉模式加上锁,上代码:
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(Objects.isNull(singleton)){
synchronized (Singleton.class){
if(Objects.isNull(singleton)){
singleton = new Singleton();
}
}
}
return singleton;
}
}
看上述代码,可以知道即使多个线程通过第一个非空检验,但是执行第二个非空检验时因为上了锁,所以只能由一个抢到锁的线程通过第二个非空检验,并进行实例化,当后面线程抢到锁发现已经有Singleton对象了就不会继续创建。虽然在性能上有点牺牲,但不会影响大体情况。
结尾
除了单例模式,还有其他22种设计模式,仅仅是学完是不够的,最重要的是要在平时的业务环境中实践起来,毕竟你练习的再多还不如一次次的实践。