設計模式之單例模式

什麼是單例模式

  單例模式,是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例。即一個類只有一個對象實例

餓漢式——當類被加載的時候便進行初始化單例對象

//直接在加載後初始化
public class SingleDemo{

    private static SingleDemo demo = new SingleDemo();
    private SingleDemo(){}

    public static SingleDemo getDemo(){
        return demo;
    }
}

//以及通過靜態代碼塊實現
public class SingleDemo{

    private static SingleDemo demo = null;
    static{
        demo = new SingleDemo();
    }

    private SingleDemo(){}

    public static SingleDemo getDemo(){
        return demo;
    }
}

缺點:
  雖然看上去餓漢模式不會有線程安全的問題,但是卻依然有一個隱含的漏洞,那就是當有多個類加載器對該對象進行裝載的時候,便會初始化多個demo對象。例如一些servlet容器對每個servlet使用完全不同的類裝載器,這樣的話如果有兩個servlet訪問一個單例類,它們就都會有各自的實例。

懶漢式——當需要使用單例對象時進行初始化操作(多版本)

版本1:

public class SingleDemo{

    private static SingleDemo demo = null;
    private SingleDemo(){}

    public static SingleDemo getDemo(){
        if(demo == null){
            demo = new SingleDemo();
        }
        return demo;
    }
}
//這是最簡單的版本,但是有個致命的問題就是,它不是一個線程安全的例子,也就是說在多線程環境下,並不總能保證單例。

版本2:

public class SingleDemo{

    private static SingleDemo demo = null;

    private SingleDemo(){}

    public synchronized static SingleDemo getDemo(){
        if(demo == null){
            demo = new SingleDemo();
        }
        return demo;
    }
}
//通過對方法上鎖,實現的線程安全的獲取單例的操作,但是很遺憾,因爲這個方法在絕大多數情況下是不需要同步的,加鎖嚴重降低了程序執行的效率,所以不提倡使用。

版本3:

public class SingleDemo{

    private static SingleDemo demo = null;

    private SingleDemo(){}

    public  static SingleDemo getDemo(){
        if(demo == null){
            synchronized(SingleDemo.class) {
                demo = new SingleDemo();
            }
        }
        return demo;
    }
}
//對版本2進行優化後,可以明顯提高程序的效率,但是很遺憾,這段代碼並不能保證線程安全。

版本4:

public class SingleDemo{

    private static SingleDemo demo = null;

    private SingleDemo(){}

    public  static SingleDemo getDemo(){
        if(demo == null){
            synchronized(SingleDemo.class) {
                if(demo == null) {
                    demo = new SingleDemo();
                }
            }
        }
        return demo;
    }
}
//這是上述版本的最終形態,俗稱雙檢鎖模式,通過雙重校驗,達到了線程安全的目的,同時避免了代碼頻繁上鎖解鎖的過程

版本5:

public class SingleDemo{

    private SingleDemo(){}

    private static class Singleton{
        private static final SingleDemo DEMO = new SingleDemo();
    }

    public  static SingleDemo getDemo(){
        return Singleton.DEMO;
    }
}
//這樣至少看起來代碼簡潔不少,不僅達到了懶加載的效果,還實現了線程安全。

版本6:

public enum SingleDemo{
    DEMO;
    public  static SingleDemo getDemo(){
        return DEMO;
    }
}
//最後這種是通過枚舉實現的單例,但是現實用到的不多,該模式爲Effective Java作者Josh Bloch 所推崇,它不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象(如果Singleton實現了java.io.Serializable接口,那麼這個類的實例就可能被序列化和復原,如果你序列化一個單例類的對象,接下來複原多個那個對象,那你就會有多個單例類的實例)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章