设计模式:单例模式

什么是单例模式

单例模式,顾名思义,就是整个系统就只有一个实例存在。

特点

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例。

讲的通俗一点,我们拿女娲造人来举例:

我们先写一个女娲类:

1
2
3
public class N_Wa {

}

很明显,任何人都不能创造女娲,所以女娲的构造应该是私有的:

1
2
3
public class N_Wa {
private N_Wa() {} // 构造方法私有化
}

有人可能要质疑:那女娲应该是谁创造的?
这个问题千百万年来都没有人能解开过,所以在我们的潜意识中认为:神是自己创造自己的!

1
2
3
4
public class N_Wa {
private static final N_Wa n_wa = new N_Wa(); // 神自己创造自己
private N_Wa() {} // 构造方法私有化
}

private 保证了女娲的私有性,毕竟这个世界上没有人见过女娲。
static 保证了女娲的静态性,她与类共存亡。
final 保证了女娲是“终极”常量,不可能再被修改。

女娲已经出来了,接下来干什么呢?
当然就是请她开始造人啦:

1
2
3
4
5
6
7
public class N_Wa {
private static final N_Wa n_wa = new N_Wa(); // 神自己创造自己
private N_Wa() {} // 构造方法私有化
public static N_Wa getInstance() { // 请求女娲
return n_wa;
}
}

getInstance 和 new?
new 是重新创建一个对象,且只能单次使用。
getInstance 是没有对象的时候创建对象,有了之后就保留在内存中,下次就不用再重新创建了,因此它的对象一定是static的。

这样一来,只需要调用 N_Wa.getInstance(); 女娲就请过来了,而且不论是谁,请来的都是同一个女娲,也就是我们构造的“终极”常量:n_wa。当然你还可以往里面加入其它的功能(造人功能未写出)。

到此为止,我们就已经学会了单例模式——“饿汉模式”,即我们先把女娲给造好,需要的时候直接用就好了。

随之而来的是另一个问题:要是我们根本没有用到女娲呢?那不是白造了?于是又出现了一种叫“懒汉模式”:

1
2
3
4
5
6
7
8
9
10
public class N_Wa {
private static N_Wa n_wa; // 这里并没有new一个女娲
private N_Wa() {} // 构造方法私有化
public static N_Wa getInstance() { // 请求女娲
if(n_wa == null) {
n_wa = new N_Wa();
}
return n_wa;
}
}

可以发现,我们不再是提前造女娲了,而是需要的时候再去造她(实例化),但这样子的坏处就是每次都要重新造一次女娲,所以速度肯定不如之前的“饿汉模式”。而且有个大问题,就是一旦有很多人同时请女娲的话,依然可能造成多个神的情况。

所以我们让这些人排队?看起来挺有道理,但仔细想想,有些人做事总是拖拖拉拉,毛手毛脚的,万一给让它排到前面去了,那后面的人不得等半天吗?等下队伍直接排出地球外了,所以我们干脆让他们直接抢,谁抢到就是谁的,这样一直抢下去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class N_Wa {
private static N_Wa n_wa; // 这里并没有new一个女娲
private N_Wa() {} // 构造方法私有化
public static N_Wa getInstance() { // 请求女娲
if(n_wa == null){ // 代表还没有人抢到
synchronized (N_Wa.class) { // 放他们进去抢
if(n_wa == null) { // 第一个抢到的给他 new一个然后返回
n_wa = new N_Wa();
}
}
}
return n_wa;
}
}

synchronized 是一种同步锁,可以防止同步发生,通俗来讲就是第一个人先用,这时锁被锁上,等他用完,锁再打开,以此类推。只有当锁是开着的,才能轮到下一个人。

到此为止,最基础的两种“恶汉模式”和“懒汉模式”就完成了,单例模式还有其它的一些变种,但思想上都大同小异,我们需要灵活运用,发挥出最大的价值!

作者

Benboby

发布于

2020-09-03

更新于

2021-01-28

许可协议

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×