概述:单例是设计模式中最常见也最简单的一种设计模式,保证了在程序中只有一个实例存在并且能全局的访问到。比如在android实际APP 开发中用到的,数据库对象(SQLiteOpenHelper)等都会用到单例模式。

常见的单例的几种写法:

一、懒汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 懒汉式单例实现的示例
*/
public class Singleton {
//4:定义一个变量来存储创建好的类实例
//5:因为这个变量要在静态方法中使用,所以需要加上static修饰
private static Singleton instance = null;
//1:私有化构造方法,好在内部控制创建实例的数目
private Singleton(){
}
//2:定义一个方法来为客户端提供类实例
//3:这个方法需要定义成类方法,也就是要加static
public static Singleton getInstance(){
//6:判断存储实例的变量是否有值
if(instance == null){
//6.1:如果没有,就创建一个类实例,并把值赋值给存储类实例的变量
instance = new Singleton();
}
//6.2:如果有值,那就直接使用
return instance;
}
}
优点:延迟加载,也就是需要时才回去加载
缺点:线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时。

二、饿汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 饿汉式单例实现的示例
*/
public class Singleton {
//4:定义一个静态变量来存储创建好的类实例
//直接在这里创建类实例,只会创建一次
private static Singleton instance = new Singleton();
//1:私有化构造方法,好在内部控制创建实例的数目
private Singleton(){
}
//2:定义一个方法来为客户端提供类实例
//3:这个方法需要定义成类方法,也就是要加static
//这个方法里面就不需要控制代码了
public static Singleton getInstance(){
//5:直接使用已经创建好的实例
return instance;
}
}
优点:饿汉式是线程安全的,因为虚拟机保证了只会装载一次,在装载类的时候是不会发生并发的。

三、双重检查加锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Singleton {
/**
* 对保存实例的变量添加volatile的修饰
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(Singleton.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
优点:在并发量不多,安全性不高的情况下或许能很完美运行单例模式
缺点:不同平台编译过程中可能会存在严重安全隐患。

四、内部类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Singleton {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
}
/**
* 私有化构造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
优点:延迟加载,线程安全(java中class加载时互斥的),也减少了内存消耗

五、单例和枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 使用枚举来实现单例模式的示例
*/
public enum Singleton {
/**
* 定义一个枚举的元素,它就代表了Singleton的一个实例
*/
uniqueInstance;
/**
* 示意方法,单例可以有自己的操作
*/
public void singletonOperation(){
//功能处理
}
}
优点:无偿的提供了序列化的机制,并由JVM从根本上提供保障,绝对防止多次实例化,

参考链接:研磨设计模式