单例模式

单例模式

单例模式,即对于一个类,只能有一个实例。由于构造函数可以新增实例,所以在所有的单例实现中,构造函数必须是private。以下列出四种常见的单例模式的实现方式。

1、枚举

1
2
3
4
public enum Singleton {
INSTANCE;
public void whateverMethod() {}
}

枚举类经过编译也会生成一个类,一个class文件。这个类会继承抽象类Enum,由于java不能多继承,所以枚举类是不能继承别的类的。枚举类中的枚举值,会变成该类中的静态常量,有几个枚举值,就会有几个静态常量。枚举能实现单例,本质上是使用了静态常量来达成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//反编译Singleton.class
final class Singleton extends Enum
{
//编译器新增的构造函数
private Singleton(String s, int i)
{
super(s, i);
}
//静态常量
public static final Singleton INSTANCE;

public void whateverMethod() {}

//静态代码块,非延时加载
static
{
INSTANCE = new Singleton("INSTANCE", 0);
}
}

2、静态常量

1
2
3
4
5
6
7
8
public class Singleton {
private Singleton(){}

private final static Singleton INSTANCE = new Singleton();
public static Singleton getInstance(){
return INSTANCE;
}
}

非延时加载,会浪费内存。

3、静态内部类

1
2
3
4
5
6
7
8
9
10
public class Singleton {
private Singleton() {}

private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}

延时加载,对内存友好。

4、双重检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton {
private Singleton() {}

private static volatile Singleton singleton;
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

注意变量singleton需要用volatile修饰,保证不被重排序和对其他线程的可见性。