初始設計模式2——單例模式

單例模式(Singleton Pattern)是一個比較簡單的模式,它保證一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。

通用代碼:

<pre name="code" class="java"><span style="font-size:14px;">public class Singleton{
  private static final Singleton singleton = new Singleton();
  private Singleton(){}//私有構造函數,使其無法類外通過new構造
  public static Singleton getSingleton(){
    return singleton;
  }
  public static void doSomething(){}//類中其他方法,儘量爲static
}</span>

單例模式通過private的構造函數確保只產生一個自行實例化的對象。

這種單例在類加載時就初始化單例,然而有時初始化單例代價比較高,希望在使用時才加載,這時可以使用Lazy loading方式的單例模式:

<pre name="code" class="java">public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  <span style="font-family: Arial, Helvetica, sans-serif;">    </span>
<pre name="code" class="java">    public static void doSomething(){}//類中其他方法,儘量爲static
}


這種方式是Singleton類被裝載了,instance不一定被初始化。因爲SingletonHolder類沒有被主動使用,只有顯示通過調用getInstance方法時,纔會顯示裝載SingletonHolder類,從而實例化instance

單例模式在內存只有一個實例,減少了內存開銷,也可以避免對資源的多重佔用。不過單例模式一般沒有抽象,擴展困難,而且也與單一職責原則衝突

單例模式擴展,有上限多例模式:

<pre name="code" class="java">public class Singleton{
  private static int manNum = 2;
  private static ArrayList<Singleton> singleton = new ArrayList<Singleton>();
  static{
    for(int i = 0; i < manNum; i ++){
      singleton.add(new Singleton());
  }
  private Singleton(){}//私有構造函數,使其類外無法通過new構造
  public static Singleton getSingleton(int countNum){
    return singleton.get(countNum);
  }
  public static void doSomething(){}//類中其他方法,儘量爲static
}

使用單例模式需要注意JVM的垃圾回收機制,如果單例對象在內存中長久不使用,JVM就會認爲這個對象是一個垃圾,在CPU資源空閒情況下會被清理掉,下次調用產生新的單例對象,如果單例類有狀態值,則會出現異常。可以使用兩種方法來避免:1.由容器管理單例的生命週期,如使用Spring可以使對象常駐內存。2.狀態隨時記錄,使用異步記錄的方法或觀察者模式,保存狀態的變化,確保單例重新初始化時可以獲得銷燬前數據。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章