設計模式總結篇系列:單例模式(SingleTon)


在Java設計模式中,單例模式相對來說算是比較簡單的一種構建模式。適用的場景在於:對於定義的一個類,在整個應用程序執行期間只有唯一的一個實例對象。如Android中常見的Application對象。

通過單例模式,自行實例化並向這個系統提供這個單一實例的訪問方法。

根據此單一實例產生的時機不同(當然,都是指第一次,也是唯一一次產生此單一實例時),可以將其分為懶漢式、餓漢式和登記式。

一、懶漢式:

其特點是延遲加載,即當需要用到此單一實例的時候,才去初始化此單一實例。常見經典的寫法如下:

 1 package com.qqyumidi;  2 
 3 public class SingleTon {  4 
 5     // 靜態實例變量
 6     private static SingleTon instance;  7 
 8     // 私有化構造函數
 9     private SingleTon() { 10 
11  } 12 
13     // 靜態public方法,向整個應用提供單例獲取方式
14     public static SingleTon getInstance() { 15         if (instance == null) { 16             instance = new SingleTon(); 17  } 18         return instance; 19  } 20 
21 }

 

懶漢式的線程安全寫法

 1 package com.qqyumidi;
 2 
 3 public class SingleTon {
 4 
 5     // 靜態實例變量加上volatile
 6     private static volatile SingleTon instance;
 7 
 8     // 私有化構造函數
 9     private SingleTon() {
10 
11     }
12 
13     // 雙重檢查鎖
14     public static SingleTon getInstance() {
15         if (instance == null) {
16             synchronized(Singleton.class){
17                 if(instance == null){
18                     instance = new SingleTon();
19                 }
20             }
21         }
22         return instance;
23     }
24 
25 }

 

 

二、餓漢式:

餓漢式的特點是應用中尚未需要用到此單一實例的時候即先實例化。常見的經典寫法為:

 1 package com.qqyumidi;  2 
 3 public class SingleTon {  4 
 5     // 靜態實例變量,直接初始化
 6     private static SingleTon instance = new SingleTon();  7 
 8     // 私有化構造函數
 9     private SingleTon() { 10 
11  } 12 
13     // 靜態public方法,向整個應用提供單例獲取方式
14     public static SingleTon getInstance() { 15         return instance; 16  } 17 
18 }

 

三、登記式單例模式:

登記式單例模式,一般是通過一個專門的類對各單例模式的此單一實例進行管理和維護。通過Map方式可以方便的實現此中目的。常見的代碼如下:

 1 package com.qqyumidi;  2 
 3 import java.util.HashMap;  4 import java.util.Map;  5 
 6 public class SingleTonManager {  7 
 8     private static Map singleTonMap = new HashMap();  9 
10     public static void main(String[] args) { 11         // 獲取A類的單例
12         A a = (A) getInstance(A.class.getName()); 13         // 獲取B類的單例
14         B b = (B) getInstance(B.class.getName()); 15  } 16 
17     // 根據類型獲取單例
18     public static Object getInstance(String className) { 19         // 判斷singleTonMap中是否有此單例,有則取得后返回,無則添加單例后返回
20         if (!singleTonMap.containsKey(className)) { 21             try { 22  singleTonMap.put(className, Class.forName(className).newInstance()); 23             } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { 24                 // TODO Auto-generated catch block
25  e.printStackTrace(); 26  } 27  } 28         return singleTonMap.get(className); 29  } 30 } 31 
32 class A { 33 
34 } 35 
36 class B { 37 
38 }

 

另外:需要注意的是,在多線程環境中,以上各種方法構造單例模式需要考慮到線程安全問題。

 

四、改進型懶漢式(直接滿足線程安全)——通過靜態內部類實現

在如上的懶漢單例模式中,對於多線程環境中。可以通過常見的如synchronized等方式實現線程安全,同時,可以通過Java靜態內部類的方式實現進一步改進。

常見代碼如下:

 

 1 package com.qqyumidi;  2 
 3 public class SingleTon {  4 
 5     // 利用靜態內部類特性實現外部類的單例
 6     private static class SingleTonBuilder {  7         private static SingleTon singleTon = new SingleTon();  8  }  9 
10     // 私有化構造函數
11     private SingleTon() { 12 
13  } 14 
15     public static SingleTon getInstance() { 16         return SingleTonBuilder.singleTon; 17  } 18 
19     public static void main(String[] args) { 20         SingleTon instance = getInstance(); 21  } 22 }

 

其主要原理為:Java中靜態內部類可以訪問其外部類的成員屬性和方法,同時,靜態內部類只有當被調用的時候才開始首次被加載,利用此特性,可以實現懶漢式,在靜態內部類中靜態初始化外部類的單一實例即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM