設計模式——單例模式

分類: Java

在某些應用的場合,一個或者某些類只需要或者只能存在一個實例,這種情況下單例模式便派上了用場。在windows操作系統中,垃圾回收站就是典型的應用,還有很多工程中的配置文件等等,系統中只需要一個實例。當系統需要該類實例時,如果系統中存在該類的實例直接返回實例。如果系統沒有該類實例時,創建一個新的類實例,從而保證系統中只存在該對象的一個實例。

系統中類實例創建主要由於其構造方法來完成的,因此在這個時候就需要控制類的初始化過程。下面有兩個例子,用不同方式產生所需類的單一實例。

 1:  餓漢式
 2:  public class EagerSingletonPattern {
 3:  
 4:  private static final EagerSingletonPattern ins = new EagerSingletonPattern();
 5:  
 6:  private EagerSingletonPattern(){
 7:      }
 8:  
 9:  public static EagerSingletonPattern getInstance(){
10:  return ins;
11:  }
12:  }

下面便是懶漢式:

 1:  懶漢式
 2:  public class LazySingletonPattern {
 3:  private static LazySingletonPattern ins = null;
 4:  
 5:  private LazySingletonPattern(){
 6:      }
 7:  
 8:  public synchronized static LazySingletonPattern getInstance(){
 9:  if( ins == null){
10:  ins = new LazySingletonPattern();
11:  }
12:  return ins;
13:  }
14:  }

餓漢式在類加載的時候便初始化該類的一個實例,系統需要該類實例時直接返回。在系統調用時響應速度較快,但系統資源利用率較低。懶漢式在需要類實例的時候,先檢查系統中是否已經存在類實例。如果存在直接返回,反之創建一個實例。系統資源利用率較高,但在系統調用時響應速度較餓漢式要慢,而且在多線程中,需要線程之間的同步,有可能在資源初始化的時候耗時比較長。

這2種實現方式基本上可以實現所需的要求。但是在懶漢式實現中,後續線程需要等待執行方法線程完成之後才能進入執行,無疑,這延長了系統響應時間。在《Head First 設計模式》書中提到了對懶漢式的一種改進,我個人認爲這種方法是正確的,儘管在《Java與模式》書中提到雙重檢查成例的不正確性。下面我給出《Head First 設計模式》中雙重檢查加鎖的例子。

 1:  public class DCLSingletonPattern {
 2:  
 3:      private volatile static DCLSingletonPattern ins= null;
 4:  
 5:      private DCLSingletonPattern(){}
 6:  
 7:      public static DCLSingletonPattern getInstance(){
 8:          if(ins == null){  //第一重檢查
 9:              synchronized(DCLSingletonPattern.class){//線程同步
10:                  if(ins == null){ //第二重檢查
11:                      ins = new DCLSingletonPattern();
12:                  }
13:              }
14:          }
15:          return ins;
16:      }
17:  }

volatile關鍵詞確保變量ins在初始化爲實例後,多線程能正確的處理ins變量。

上面給出的例子都或多或少都存在一些缺陷,它們的通病都在於其不能被子類所繼承。如果能被子類所繼承的話,其構造方法至少爲protect,而不能爲private。但是如果修改成protect,該類就失去了單例模式的特性--其他類可以直接調用其構造方法產生新的實例。因此,在《Java與模式》中給出了登記式的實現方法。但是子類構造方法也不能爲private,其構造方法對外開放或部分開放,只能按照登記式實例化可以產生單例,因而也並不完美。在此,我就不給這個例子了,實際應用中,懶漢式和餓漢式基本上夠用。


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