背景
单例的一般写法,大家基本都会,这里特指具有以下特征的单例:
1.单例
2.需要延迟加载
3.线程安全
看一下这个类的写法(JAVA):
public class A {
private static final AtomicReference<A> ref = new AtomicReference<>();
private A() {
}
public static A get() {
A ret = ref.get();
if (ret == null) {
synchronized (ref) {
if (ref.get() == null) {
ret = new A();
} else {
ret = ref.get();
}
}
}
return ret;
}
}
问题:
这样写是没问题。我们大部分时候也都这么写。
如果我们有好几个类都要写单例怎么办,A,B,C….?挨个搞一遍?万一以上代码出了问题,需要修复,再挨个修复一遍?显然不能这么搞。
解决方法
我观察了一下这些类的规律,整个类的代码基本相同,只有对象创建部分不同。根据OO的基本特性,我们可以把这部分不一样的代码,放到子类里去,延迟实现。
我们可以这样一个辅助类,我称它为“抽象单例”:
/**
* 线程安全的抽象单例
*
* @author zhmt
* @createdate 2016年3月4日 下午4:39:50
* @param <T>
*/
public abstract class AbstractSingleton<T> {
private final AtomicReference<T> ref = new AtomicReference<T>();
public T get() {
T ret = ref.get();
if (ret == null) {
synchronized (this) {
if (ref.get() == null) {
ret = newObj();
ref.set(ret);
} else {
ret = ref.get();
}
}
}
return ret;
}
protected abstract T newObj();
}
通过这个类,我们就把对象创建的操作延后了。
现在,再看我们怎么实现A的单例:
public class A {
public static final AbstractSingleton<A> objHolder = new AbstractSingleton<A>() {
protected A newObj() {
return new A();
}
};
private A() {
A.objHolder.get();
}
}
这里只需要写几行简单的代码,而不是复杂易错的初始化过程,这样,以后所有类似的单例都得到了简化。
获取A的单例:
A.objHolder.get();
这样,以后再需要单例的时候,我只需要声明一个AbstractSingletion对象,并实现newObj方法即可。
如果你有更好的办法,欢迎讨论。