什麼是Singleton呢?
In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist. It is also considered an anti-pattern since it is often used as a euphemism for global variable.
http://en.wikipedia.org/wiki/Singleton_pattern
翻譯:
在軟體工程領域,Singleton是一種將對象的執行個體限制為只有一個的一種模式。當系統的所有處理只需要某個對象的一個執行個體的時候可以適用這種模式。通常情況下,執行個體存在的越少(最好是一個)系統的效能越好。針對於Singleton的反模式是使用全域變數。
在wikipedia上Java的標準實現是:
public class Singleton
{
// 通過私人化構造方法,防止在Singleton類之外構造類的執行個體。
private Singleton() {}
/**
* SingletonHolder 在Singleton.getInstance()第一次調用的時候被初始化。
*/
private static class SingletonHolder
{
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance()
{
return SingletonHolder.INSTANCE;
}
}
或者更常見的是:
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
// 通過私人化構造方法,防止在Singleton類之外構造類的執行個體。
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
關於Singleton的說明
第一,必須保證在類的外部不能調用構造方法。
在預設無構造方法的情況下,Java編譯器會給類加上一個沒有參數的共有的(Public)構造方法(預設構造方法),有構造方法的情況下Java編譯器保留定義的構造方法。所以在使用Singleton的時候,如果有構造參數則需要將存取修飾詞改為private的,沒有構造參數的情況下,需要添加一個私人的預設構造方法。私人的預設構造方法參看上述代碼。
private Singleton() {}
第二,必須有一個類的執行個體
為了避免在累得外面執行個體化類,所以在第一步中將構造參數設定為了私人,所以只能在類的內部執行個體化,參看上述代碼。
private final static Singleton INSTANCE = new Singleton();
第三,在類的外部必須能夠訪問到第二步中建立的執行個體。
由於類不能被執行個體化,所以擷取類內部的執行個體的方法必須為靜態。參看代碼:
public static Singleton getInstance() {
return INSTANCE;
}
這個時候也明白了第二步中,INSTANCE執行個體為什麼是static的了,final只是為了強調INSTANCE被初始化之後即不可改變,更見強調了singleton的含義。
關於Singleton的一些變化
如果一個Singleton類需要初始話怎麼辦呢?有兩個方法
第一種方法,添加靜態程式碼片段
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
static{
// 在這裡初始化Singleton的執行個體INSTANCE
}
// 通過私人化構造方法,防止在Singleton類之外構造類的執行個體。
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
第二種方法,在getInstance的時候初始化
public class Singleton {
private static Singleton INSTANCE;
// 通過私人化構造方法,防止在Singleton類之外構造類的執行個體。
private Singleton() {}
public static Singleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new Singleton();
//初始化代碼
}
return INSTANCE;
}
}
另種方法採用的原則是,如果肯定會使用到這個執行個體,可以採用第一種方法;如果可能使用到這個執行個體,可以使用第二種方法。
Singleton初始化異常處理
Singleton執行個體初始化的時候可能會出現一些異常,通常情況下可以不考慮,如果使用上述的第一種方法,執行個體化時發生在代碼裝載的時候,除了日誌不可能給使用者反饋。如果使用第二種方法,可以在使用者調用的時候處理,可以在getInstance方法介面添加拋出異常便於使用者處理。
所以如果Singleton初始化會拋出異常,且此類異常需要客戶處理的時候需要使用上述的第二種方法。