單例模式是設計模式中使用最普遍的模式之一,它是一種對象創建模式,用於創建一個對象的具體示事例,它可以確保系統中一個類只產生一個實例。
使用單例設計模式給我帶來的好處就是:
1,對於頻繁使用的對象,可以省略創建對象所花費的時間
2,由於new的次數減少,因而對內存的使用頻率也會降低,這將減輕GC壓力,因此,使用單例模式便可以有效的改善系統性能
單例模式的核心在於通過一個接口返回唯一的對象事例,下面的示例即爲一個簡單的單例模式設計:
public class Singleton {
private Singleton(){
}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
}
注意:單例類必須要有一個私有的構造方法,用來防止類被系統中的其它代碼實例化,其次,成員變量和方法是static的。
上面這種單例的設計模式俗稱惡漢式,非常簡單可靠,但不足之處就是無法對singleton實例做延遲加載。加入單例的創建過程很慢,而成員變量又是靜態的,因此jvm加載單例類時,單例對象就會被創建,而此時,如果這個單例類在系統的其它地方使用在,那麼使用這個單例類的地方都會初始化這個成員變量,而不管是否被使用到,相當於我們並沒有使用單例類,但是它還是會被創建出來。爲了解決這個問題,並提高系統在相關函數調用時的反應速度,就需引入延遲加載機制。
public class Singleton {
private Singleton() {
}
private static Singleton singleton = null;
public synchronized static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
上面的示例中:對靜態成員變量賦值null保證啓動時沒有額外的負載,其次在靜態方法中判斷是否又singleton的實例,沒有則創建,有則直接返回,注意的一點是,這個方法須是同步的,否則在多線程中會導致多個實例被創建。
上面的這種設計方式相對於第一種方式來說,雖然實現了延遲加載的功能,然而它引入了同步鎖,因此在多線程環境中,它的耗時要比第一種大很多,因此爲了解決這個問題,還需要對其進行改進。
public class Singleton {
private Singleton() {}
private static class SingletonHandler{
private static Singleton singleton = new Singleton();
}
public synchronized static Singleton getInstance() {
return SingletonHandler.singleton;
}
}
這個設計方法中:單例模式內部使用內部類來實例化一個單例的實例,這樣當Singleton類被加載時,其內部類並不會被實例化,故當類被加載進jvm中的時候,單例對象並不會被實例化,而當getInstance方法被調用時纔會加載內部類並實例化singleton。因此這種方法同時兼備上面兩種實現的優點。
使用內部類的方法來實現單例,既可以做到延遲加載,也不必使用同步關鍵字,是一種比較完善的實現。