01設計模式 -- 單例模式
阿新 • • 發佈:2018-11-19
設計模式之單例模式
定義:單例模式主要作用是保證在Java應用程式中,一個類Class只有一個例項存在
單例模式為我們提供了這樣的實現。使用單例的好處還在於可以節省記憶體,因為它限制了例項的個數,有利於Java的垃圾回收(garbage collection)。
我們常常看到工廠模式中類載入器(class loader)中也是用單例模式來實現,因為被裝入的來實際也屬於資源。
使用:一般單例模式通常有兩種形式 -- 懶漢式和餓漢式
懶漢式:第一次呼叫時初始化,避免記憶體浪費,使用雙重檢查可以保證在多執行緒情況的執行緒安全
1 public class Singleton {2 private static Singleton instance = null; 3 /** 4 * 讓建構函式私有化,這樣該類就不會在類外被例項化 5 */ 6 private Singleton() { 7 } 8 public static Singleton getInstance() { 9 // 第一次使用時生成物件 10 if (instance == null) { 11 synchronized (Singleton.class) { 12 if(instance == null) { 13 instance = new Singleton(); 14 } 15 } 16 } 17 return instance; 18 } 19 }
餓漢式:類載入時初始化,執行緒安全,執行效率高,但是容易產生垃圾物件
1 public class Singleton { 2 // 在類裝載時就例項化Singleton的一個物件 3 private static Singleton instance = newSingleton(); 4 5 /** 6 * 讓建構函式私有化,這樣該類就不會在類外被例項化 7 */ 8 private Singleton(){} 9 10 /** 11 * 提供一個供外部訪問的方法獲取唯一可用的物件 12 * @return 返回唯一可用的物件 13 */ 14 public static Singleton getInstance(){ 15 return instance; 16 } 17 18 // 類中其他方法儘量被public修飾,方便被外界直接呼叫 19 }
使用場景:要求一個類有且僅有一個物件,就可以採用單例模式。
最佳實踐:在spring中,每個bean預設使用的就是單例,這樣做的優點是Spring容器可以管理這些bean的生命週期。如果採用非單例模式,則bean初始化話後的管理交給J2EE容器,Spring不再管理。
注意事項:使用單例模式需要注意的一點時JVM的垃圾回收機制。當一個單例物件在記憶體中長久不使用,在CPU空閒的時候該物件會被清理掉,下次再呼叫的時候再重新建立一個物件,這樣如果我們在應用中使用該單例類作為類似計數器等管理,就會出現恢復原狀的故障。如果確定使用單例模式來作為類似計數器等作用,可以使用下面的方法來解決此問題
- 由容器管理單例的生命週期:JavaEE容器或者框架的容器(如Spring)可以讓物件長久貯存。
- 狀態隨時記錄:使用非同步的方式,記錄狀態的變化,寫入資料庫,確保單例物件在重新初始化的時候也可以從儲存的資源中獲得銷燬前的資料,避免資料丟失。
單例模式還有多種設計方式,這裡不再一一贅述,大家有想法可以留言一起交流。