顧名思義就是只能存在一份物件。
獨體模式最大的特色就是把建構子設為private, 不讓其他的程式設計師能夠透過new將其物件生出。
但是獨體模式有存在許多種寫法, 但是如果不清楚用意, 很容易寫出錯誤的獨體模式,
最常誤用的就是這種。
- 非Singleton(常誤用)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
這其實不算是獨體模式, 因為它在多執行緒內, 有機會能夠產生一個以上的物件。那該怎麼改善這種寫法確保只會產生一種物件呢?
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
只要加入synchronized關鍵字, 就可以對這個方法上鎖, 也就是說同時間只會有單一thread能夠處理這個方法, 當然這個也會有壞處, 就是效能上的問題。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
接下來這個寫法是比較推薦的, Android Studio可自動產生一個singleton類別, 可以看到非常簡單的地方就是它一開始在編譯時期就new出Singleton物件,
因此是Thread Safe的, 但是缺點就是初始化如果是非常複雜的物件,
則第一次執行會拖慢整個程式的運行, 如果沒有用到該物件,
仍會生成該物件。
- 雙重瑣Singleton
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if(singleton == null) {
synchronized (Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 靜態類別Singleton
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
這種Singleton是建立在一個靜態類別, 執行時期有call getInstance才會進行初始化, 有達到lazy loading的效果, 如果沒有用到此物件, 則不會生成。
- 列舉Singleton
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
這種寫法不但可以防止多執行緒的問題, 也有防止序列化的話。 不過實作上非常少見。