設計模式讀書筆記-----單例模式


        有時候某些對象我們只需要一個,如:線程池、緩存、對話框等等,對於這類對象我們只能有一個實例,如果我

們制造出多個實例,就會導致很多問題產生。

        但是我們怎樣才能保證一個類只有一個實例並且能夠便於訪問?這里我們想到了全局變量,全局變量確實是可以

保證該類可以隨時訪問,但是它很難解決只有一個實例問題。最好的辦法就是讓該自身來負責保存它的唯一實例。這

個類必須要保證沒有其他類來創建它。這里我們可以將其構造方法私有化。即

1 Public MyClass{
2          PrivateMyClass(){}
3 }

        含有私有化構造器的類就能保證它不能被其他類實例化了。但是我們如何來獲取這個實例化類呢?提供一個方法

用於返回該類的實例對象即可實現。

 

1 public class MyClass {
2     private MyClass(){
3         
4     }
5     
6     public static MyClass getInstance(){
7         return new MyClass();
8     }
9 }

        一、基本定義                                                                                                       

 

        通過上面簡單介紹,我們可以對單例模式有一個簡單的認識。所謂單例模式就是確保某一個類只有一個實例,並

且提供一個全局訪問點。

        從上面可以看出單例模式有如下幾個特點:

           一、它只有一個實例。

           二、它必須要自行實例化。

           三、它必須自行想整個系統提供訪問點。

 

        二、模式結構                                                                                                       

         單例模式可以說是最簡單的設計模式了,它僅有一個角色Singleton。

         Singleton:單例。

 

         三、模式實現                                                                                                       

 1 public class Singleton {
 2     //利用靜態變量來記錄Singleton的唯一實例
 3     private static Singleton uniqueInstance;
 4     
 5     /*
 6      * 構造器私有化,只有Singleton類內才可以調用構造器
 7      */
 8     private Singleton(){
 9         
10     }
11     
12     public static Singleton getInstance(){
13         if(uniqueInstance == null){
14             uniqueInstance = new Singleton();
15         }
16         
17         return uniqueInstance;
18     }
19     
20 }

 

         在《Head  First》有這樣一個場景,就是說有兩個線程都要執行這段代碼,很有可能會產生兩個實例對象。如下圖:

         這里有三種解決方案。

           第一、  使用synchronized來處理。也就是說將getInstance()方法變成同步方法即可。

 1 public class Singleton {
 2     //利用靜態變量來記錄Singleton的唯一實例
 3     private static Singleton uniqueInstance;
 4     
 5     /*
 6      * 構造器私有化,只有Singleton類內才可以調用構造器
 7      */
 8     private Singleton(){
 9         
10     }
11     
12     public static synchronized Singleton getInstance(){
13         if(uniqueInstance == null){
14             uniqueInstance = new Singleton();
15         }
16         
17         return uniqueInstance;
18     }
19     
20 }

 

          第二、  直接初始化靜態變量。這樣就保證了線程安全。

 1 public class Singleton {
 2     /*
 3      * 利用靜態變量來記錄Singleton的唯一實例
 4      * 直接初始化靜態變量,這樣就可以確保線程安全了
 5      */
 6     private static Singleton uniqueInstance = new Singleton();
 7     
 8     /*
 9      * 構造器私有化,只有Singleton類內才可以調用構造器
10      */
11     private Singleton(){
12         
13     }
14     
15     public static Singleton getInstance(){
16         return uniqueInstance;
17     }
18     
19 }

 

           第三、  用“雙重檢查加鎖”,在getInstance()中減少使用同步。

 1 public class Singleton {
 2     /*
 3      * 利用靜態變量來記錄Singleton的唯一實例
 4      * volatile 關鍵字確保:當uniqueInstance變量被初始化成Singleton實例時,
 5      * 多個線程正確地處理uniqueInstance變量
 6      * 
 7      */
 8     private volatile static Singleton uniqueInstance;
 9     
10     /*
11      * 構造器私有化,只有Singleton類內才可以調用構造器
12      */
13     private Singleton(){
14         
15     }
16     
17     /*
18      * 
19      * 檢查實例,如果不存在,就進入同步區域
20      */
21     public static Singleton getInstance(){
22         if(uniqueInstance == null){
23             synchronized(Singleton.class){    //進入同步區域
24                 if(uniqueInstance == null){     //在檢查一次,如果為null,則創建
25                     uniqueInstance  = new Singleton();
26                 }
27             }
28         }
29         
30         return uniqueInstance;
31     }
32     
33 }

           在這里是首先檢查是否實例已經創建了,如果尚未創建,才會進行同步。這樣一來。只有第一次會同步。

 

           四、模式優缺點                                                                                                     

           優點

              一、節約了系統資源。由於系統中只存在一個實例對象,對與一些需要頻繁創建和銷毀對象的系統而言,單

例模式無疑節約了系統資源和提高了系統的性能。

             二、因為單例類封裝了它的唯一實例,所以它可以嚴格控制客戶怎樣以及何時訪問它。

         缺點

             一、由於單例模式中沒有抽象層,因此單例類的擴展有很大的困難。

             二、單例類的職責過重,在一定程度上違背了“單一職責原則”。

 

           五、模式使用場景                                                                                             

           下列幾種情況可以使用單例模式。

              一、系統只需要一個實例對象,如系統要求提供一個唯一的序列號生成器,或者需要考慮資源消耗太大而只允許創建一個對象。

             二、客戶調用類的單個實例只允許使用一個公共訪問點,除了該公共訪問點,不能通過其他途徑訪問該實例。

 

           六、總結                                                                                                           

           1. 單例模式中確保程序中一個類最多只有一個實例。

           2. 單例模式的構造器是私有了,而且它必須要提供實例的全局訪問點。

           3. 單例模式可能會因為多線程的問題而帶來安全隱患。


免責聲明!

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



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