Singleton

使用時機使用時機

在設計階段你知道所要產生物件的具體類別。

  • 你所要產生的物件,代表某種單一(而且通常是共享)的資源,例如檔案系統、I/O Port。
  • 這種單一資源物件,本身會紀錄某些狀態,
  • 針對這種單一資源,只需要產生一個物件來代表就可以了。如果產生多份物件但卻代表相同的資源,不只浪費記憶體,還要確保這多份物件狀態必須一致,會增加程式的複雜度。

from: Creational Patterns要解決什麼問題(中)?

實作方法

方法1: lazy Initialization

not thread-safe

public class Singleton {
    private static Singleton instance;
    private Singleton (){};

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

方法2: lazy Initialization + synchronized

thread-safe,但效能不好

public class Singleton {
    private static Singleton instance;
    private Singleton (){};

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

方法3: double-checked locking

第一次建立實例才會做同步

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;  
    }
}

方法4:

class 加載時就初始化,浪費記憶體

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){};

    public static Singleton getInstance() {  
        return instance;  
    }  
}

方法5: initialization demand holder

public class Singleton {  
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }  
    private Singleton (){};

    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}

方法6: 使用 enum

public enum Singleton {  
    INSTANCE;

    public void whateverMethod() {
    }  
}

from: 設計模式乾貨系列:(四)單例模式