單例模式的實現方法有很多,餓漢和飽漢 ,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();
}