单例模式的实现方法有很多,饿汉和饱汉 ,Double-check Locking的模式, Registry of Singleton 模式
这里介绍下单例策略
在dom4j中就生成DocumentFactory工厂单例的时候就有单例策略的使用。
策略的介面如下:
public interface SingletonStrategy {
/**
* return a singleton instance of the class specified in setSingletonClass
*/
Object instance();
/**
* reset the instance to a new instance for the implemented strategy
*/
void reset();
void setSingletonClassName(String singletonClassName);
}
策略的两个实作:
1、
public class SimpleSingleton implements SingletonStrategy {
//singletonClassName 需要被实例化成单例的类名,在DocumentFactory 中通过配置文件传值
private String singletonClassName = null;
//singletonInstance 通过 reset() 返回单例的实例对象
private Object singletonInstance = null;
public SimpleSingleton() {
}
//只是返回实例的对象方法
public Object instance() {
return singletonInstance;
}
//used by setSingletonClassName() 产生不同的单例实例对象
public void reset() {
if (singletonClassName != null) {
Class clazz = null;
try {
clazz = Thread.currentThread().getContextClassLoader().loadClass(
singletonClassName);
singletonInstance = clazz.newInstance();
} catch (Exception ignore) {
try {
clazz = Class.forName(singletonClassName);
singletonInstance = clazz.newInstance();
} catch (Exception ignore2) {
}
}
}
}
//传进去singletonClassName 生成 一个实例 ,通过instance()取得单例
public void setSingletonClassName(String singletonClassName) {
this.singletonClassName = singletonClassName;
reset();
}
}
2、每个线程一个单例实例对象,没这么用过不知道一般用在什么地方
public class PerThreadSingleton implements SingletonStrategy {
private String singletonClassName = null;
private ThreadLocal perThreadCache = new ThreadLocal();
public PerThreadSingleton() {
}
//重置每个线程的单例对象
public void reset() {
perThreadCache = new ThreadLocal();
}
//
public Object instance() {
Object singletonInstancePerThread = null;
// use weak reference to prevent cyclic reference during GC
WeakReference ref = (WeakReference) perThreadCache.get();
// singletonInstancePerThread=perThreadCache.get();
// if (singletonInstancePerThread==null) {
if (ref == null || ref.get() == null) {
Class clazz = null;
try {
clazz = Thread.currentThread().getContextClassLoader().loadClass(
singletonClassName);
singletonInstancePerThread = clazz.newInstance();
} catch (Exception ignore) {
try {
clazz = Class.forName(singletonClassName);
singletonInstancePerThread = clazz.newInstance();
} catch (Exception ignore2) {
}
}
perThreadCache.set(new WeakReference(singletonInstancePerThread));
} else {
singletonInstancePerThread = ref.get();
}
return singletonInstancePerThread;
}
public void setSingletonClassName(String singletonClassName) {
this.singletonClassName = singletonClassName;
}
}
3、需要实现的单例类
public class DocumentFactory implements Serializable {
//关联一个单例策略对象
private static SingletonStrategy singleton = null;
protected transient QNameCache cache;
/** Default namespace prefix -> URI mappings for XPath expressions to use */
private Map xpathNamespaceURIs;
// used by getInstance() 创建单例策略对象 并将DocumentFactory 的classname set 给它 ,返回单例策略对象
private static SingletonStrategy createSingleton() {
SingletonStrategy result = null;
//通过配置文件得到DocumentFactory 的classname
String documentFactoryClassName;
try {
documentFactoryClassName = System.getProperty("org.dom4j.factory",
"org.dom4j.DocumentFactory");
} catch (Exception e) {
documentFactoryClassName = "org.dom4j.DocumentFactory";
}
try {
String singletonClass = System.getProperty(
"org.dom4j.DocumentFactory.singleton.strategy",
"org.dom4j.util.SimpleSingleton");
Class clazz = Class.forName(singletonClass);
result = (SingletonStrategy) clazz.newInstance();
} catch (Exception e) {
result = new SimpleSingleton();
}
result.setSingletonClassName(documentFactoryClassName);
return result;
}
public DocumentFactory() {
init();
}
/**
* <p>
* Access to singleton implementation of DocumentFactory which is used if no
* DocumentFactory is specified when building using the standard builders.
* </p>
*
* @return the default singleon instance
*/
//DocumentFactory 创建自己的方法 线程安全的
public static synchronized DocumentFactory getInstance() {
if (singleton == null) {
singleton = createSingleton();
}
return (DocumentFactory) singleton.instance();
}