设计模式-单例模式

定义

Ensure a class has only one instance,and provide a global point of access to it.

保证一个类只有一个实例并且提供给目标去访问它。

通过给单例类声明一个私有的构造函数,使得其他类无法去对它实例化,只允许自己进行实例化。

类图和代码

单例模式比较简单,只需要保证在外部不能被实例化,并且在多线程场景下,在多个线程同时获取单例的时候不会返回多个实例。通用代码如下:

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {

private static Singleton singleton = new Singleton();

private Singleton() {
}

public static Singleton getInstance(){
return singleton;
}
}

通常情况下,这种方式也被称为“饿汉式”,意思为会首先创建好,无论需不需要。

当然还有一种懒汉式:

1
2
3
4
5
6
7
8
9
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
}
public static Singleton getInstance(){
if(singleton == null) singleton = new Singleton();
return sintleton;
}
}

不过懒汉式并不推荐使用,因为假如有两个线程同时进入了getInstance方法,判断singleton为空,那么两个线程各自创建一个实例,就不满足单例模式了。

用的最广泛的,就是双重检查锁的方式了,懒加载、效率高、线程安全:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Singleton {

private static Singleton singletonInstance = null;

private Singleton() {

}

public Singleton getInstance(){
if (singletonInstance == null) {
synchronized (this){
if(singletonInstance == null){
singletonInstance = new Singleton();
}
}
}
return singletonInstance;
}
}

当然还可以内部类的方式,JVM的类加载机制保证了线程安全,并且延迟加载:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {

private Singleton() {
}

public static Singleton getInstance(){
return InnerSingleton.INSTANCE;
}

private static class InnerSingleton{
private final static Singleton INSTANCE = new Singleton();
}
}

在《Java Effective》里还有一种写法,即用枚举的方式,原理和内部类是类似的,只不过不像内部类一样懒加载。

1
2
3
4
5
6
7
8
9
10
11
public enum Singleton {
INSTANCE;

public void test(){
System.out.println("hello");
}

public static void main(String[] args) {
Singleton.INSTANCE.test();
}
}
坚持原创、技术分享。请作者喝杯茶吧!