Singleton Pattern(獨體模式)

Singleton Pattern(獨體模式) 獨體模式(Sigleton Pattern)是最容易入手的一個模式。
顧名思義就是只能存在一份物件。
獨體模式最大的特色就是把建構子設為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() {
        }
}
這種寫法不但可以防止多執行緒的問題, 也有防止序列化的話。
不過實作上非常少見。