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

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

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

根據此單一實例產生的時機不一樣(固然,都是指第一次,也是惟一一次產生此單一實例時),能夠將其分爲懶漢式、餓漢式和登記式。安全

1、懶漢式:多線程

其特色是延遲加載,即當須要用到此單一實例的時候,纔去初始化此單一實例。常見經典的寫法以下:函數

 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 }

 

懶漢式的線程安全寫法ui

 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 }

 

 

2、餓漢式:spa

餓漢式的特色是應用中還沒有須要用到此單一實例的時候即先實例化。常見的經典寫法爲:線程

 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 }

 

3、登記式單例模式:設計

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

 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 }

 

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

 

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

在如上的懶漢單例模式中,對於多線程環境中。能夠經過常見的如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中靜態內部類能夠訪問其外部類的成員屬性和方法,同時,靜態內部類只有當被調用的時候纔開始首次被加載,利用此特性,能夠實現懶漢式,在靜態內部類中靜態初始化外部類的單一實例便可。

相關文章
相關標籤/搜索