单例模式的定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例
单例模式的使用场景
确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源,这时就要考虑使用单利模式。
单例模式UML类图
* 构造函数不对外开放,一般为Private。
* 通过一个静态方法或者枚举返回单例类对象。
* 确保单例类的对象有且只有一个,尤其是在多线程环境下。
* 确保单例类对象在反序列化时不会重新构建对象。
示例
- ###饿汉模式:是在声明静态对象时就已经初始化
public class Single {
private static final Single single=new Single();
private Single(){
}
public static Single getInstance(){
return single;
}
}
在声明时就初始化对象,保证了对象的唯一性。
* ###懒汉模式:是声明一个静态对象,并且在用户第一次调用getInstance时进行初始化。
public class Single {
private static Single single;
private Single() {
}
public static synchronized Single getInstance() {
if (single == null) {
single = new Single();
}
return single;
}
}
其中synchronized用于在多线程情况下保证单例对象唯一性。优点:在使用时才被实例化,节约了资源。缺点:第一次加载时需要实例化,反应慢,每次调用getInstance都进行同步,造成没必要的开销。一般不建议使用这种方式。
* ###Double Check Lock(DCL)实现单例
public class Single {
private static Single single = null;
private Single() {
}
public static Single getInstance() {
if (single == null) {
synchronized (Single.class) {
if (single == null) {
single = new Single();
}
}
}
return single;
}
}
优点:在需要时初始化单例,能够保证线程安全,对象初始化后调用getInstance不进行同步锁。缺点:第一次加载时反应较慢。是使用最多的单例实现方式。
* ###静态内部类单例模式
public class Single {
private Single() {
}
public static Single getInstance() {
return SingleHolder.single;
}
private static class SingleHolder {
private static final Single single = new Single();
}
}
第一次调用getInstance方法会导致虚拟机加载SingleHolder类,能够保证线程安全、单例对象的唯一性,延迟了单例的实例化,是推荐使用的单例模式实现方式。