Head First設計模式總結(五) 單件模式
阿新 • • 發佈:2018-12-19
本文基於《Head First 設計模式》一書,對單件模式進行了概括和總結
單件模式確保一個類只有一個例項,並提供一個全域性訪問點 有一些物件我們只需要一個,比方說:執行緒池(threadpool)、快取(cache)、對話方塊、處理偏好設定和登錄檔(registry)的物件、日誌物件,充當印表機、顯示卡等裝置的驅動程式的物件。事實上,這類物件只能有一個例項,如果製造出多個例項,就會導致許多問題產生,例如:程式的異常行為、資源使用過量,或者是不一致的結果。
建立單件模式的步驟如下:
步驟 1
建立一個SingleObject類
public class SingleObject { //建立 SingleObject 的一個物件 private static SingleObject instance = new SingleObject(); //讓建構函式為 private,這樣該類就不會被例項化 private SingleObject(){} //獲取唯一可用的物件 public static SingleObject getInstance(){ return instance; } public void showMessage(){ System.out.println("Hello World!"); } }
步驟 2
從Singleton類獲取唯一的物件
public class SingletonPatternDemo { public static void main(String[] args) { //不合法的建構函式 //編譯時錯誤:建構函式 SingleObject() 是不可見的 //SingleObject object = new SingleObject(); //獲取唯一可用的物件 SingleObject object = SingleObject.getInstance(); //顯示訊息 object.showMessage(); } }
步驟 3
執行程式,得到結果 Hello World!
下面給出幾種特殊情況下的單件模式
1、懶漢式 (同步getInstance方法) (執行緒不安全)
特點:這種方式是最基本的實現方式,這種實現最大的問題就是不支援多執行緒。因為沒有加鎖 synchronized,所以嚴格意義上它並不算單例模式。 這種方式 lazy loading 很明顯,不要求執行緒安全,在多執行緒下不能正常工作。
public class Singleton{ private static Singleton uniqueInstance ; private Singleton(){} public static synchronized Singleton getInstance(){ //同步解決了多執行緒的安全問題,但效能變差 if(uniqueInstance == null){ //懶漢式,當要用時才例項化變數 uniqueInstance = new Singleton(); } return uniqueInstance; } } //同步會降低程式的效能,同步一個方法可能會使程式的執行效率下降100倍,當getInstance方法在不頻繁的地方使用時,可以同步該方法。
2、急切例項化(執行緒安全) 特點:這種方式比較常用,但容易產生垃圾物件。優點是沒有加鎖,執行效率高,缺點是類載入時就初始化了,浪費記憶體。
public class Singleton{
private static Singleton uniqueInstance = new Singleton();//保證了執行緒安全
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance;
}
}
3、雙重檢查加鎖 (若效能為關注的重點,那麼這個方法可以提高程式效能,該方法不適用於java1.4及更早的版本)
public class Singleton{
private static volatile Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null){
synchronized(Singleton.class){
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
//volatile關鍵字確保:當uniqueInstance變數被初始化為Singleton例項時,多個執行緒能正確的處理uniqueInstance變數。
4、登記式(靜態內部類) 特點:這種方式能達到雙檢鎖方式一樣的功效,但實現更簡單。對靜態域使用延遲初始化,應使用這種方式而不是雙檢鎖方式。這種方式只適用於靜態域的情況,雙檢鎖方式可在例項域需要延遲初始化時使用。
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
5、列舉 特點:這種實現方式還沒有被廣泛採用,但這是實現單例模式的最佳方法。它更簡潔,自動支援序列化機制,絕對防止多次例項化。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}