懶漢式單例
懶漢式單例類在第一次被引用時將自己執行個體化。這種簡單實現的問題在於,每次訪問getInstance()都需要同步操作,而事實上同步只在第一次訪問時有意義。
public class LazySingleton {
private static LazySingleton m_intance=null;
//私人構造方法,避免外部建立執行個體
private LazySingleton(){
}
// 靜態Factory 方法,返回此類的唯一執行個體.
// 當發現執行個體沒有初始化的時候,才初始化.
//通過synchronized關鍵字,同步了不同線程對getInstance()的訪問。
synchronized public static LazySingleton getInstance(){
if(m_intance==null){
m_intance=new LazySingleton();
}
return m_intance;
}
}
餓漢式單例
在類被載入時,就會將自己執行個體化。
public class EagerSingleton {
// 私人的(private)唯一(static final)執行個體成員,在類載入的時候就建立好了單例對象
private static final EagerSingleton m_instance = new EagerSingleton();
// 私人構造方法,避免外部建立執行個體
private EagerSingleton() {
}
// 靜態Factory 方法,返回此類的唯一執行個體.
public static EagerSingleton getInstance() {
return m_instance;
}
登記式單例
登記式單例類是GoF 為了克服餓漢式單例類及懶漢式單例類均不可繼承的缺點而設計的。
這個單例實際上維護的是一組單例類的執行個體,將這些執行個體存放在一個Map(登記薄)中,對於已經登記過的執行個體,則從工廠直接返回,對於沒有登記的,則先登記,而後返回。
import java.util.HashMap;
import java.util.Map;
public class RegSingleton {
// 登記薄,用來存放所有登記的執行個體
private static Map<String, RegSingleton> m_registry = new HashMap();
//在類載入的時候添加一個執行個體到登記薄
static {
RegSingleton x = new RegSingleton();
m_registry.put(x.getClass().getName(), x);
}
// 受保護的預設構造方法
protected RegSingleton() {
}
// 靜態Factory 方法,返回指定登錄物件的唯一執行個體;
// 對於已登記的直接取出返回,對於還未登記的,先登記,然後取出返回
public static RegSingleton getInstance(String name) {
if (name == null) {
name = "RegSingleton";
}
if (m_registry.get(name) == null) {
try {
m_registry.put(name,(RegSingleton) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return m_registry.get(name);