最經常使用的設計模式(單例模式)

  記得剛開始涉足程序的時候, 去筆試 ,發現有一個筆試題常常粗線,寫一個單例模式的基本實現, 當時沒研究設計模式也就不知爲什麼物,java

  到今日  , 才發現它已成爲我平常開發最經常使用的一種設計模式。c++

  我寫的全部設計模式的代碼都會用java 呈現, 雖然第一個學習的是c++可是 最開始做爲工做的是java,而且有點偏好javac#

  單例模式 , 意思就是 整個系統僅只有此類的一個實力, 固然這只是狹義的單例,常常看到變種的單例是容許,建立指定數量的實例的設計模式

  單例模式是一種建立型模式。 它是優化的一種策劃, 避免重複建立銷燬一個對象(建立銷燬對象是有開銷的), 有點像對象池的概念。安全

  

  我寫博文  純粹是對本身所瞭解的東西的一個回顧,  不保證權威性。  僅但願 迷途的新手能在個人博文中 有所收穫,我也儘可能 用我最簡單的語言 去描述 我對 不少東西的理解、(這段話會在個人每個博文裏面出現 由於 我不是一個看了書 作筆記的博客, 而是我進行思考的博客 ,固然也但願大牛能夠批評指正)多線程

 

  下面給出一個最簡單的單例的實現函數

 1 public class HelloSingleton {
 2     
 3     private static HelloSingleton w_Instance = new HelloSingleton();
 4 
 5     //定義一個私有的構造函數,確保在該類的外部沒法生成類的實例
 6     private HelloSingleton(){
 7         
 8     }
 9     
10     public static HelloSingleton getInst(){
11         return w_Instance;
12     }
13 }

這一種單例模式被成爲餓漢模式, 其實意思就是開始的時候就實例好了 對象, 缺點是沒有作到延遲加載 (延遲加載是一種優化策略,在須要的時候再去加載)這個用起來比較簡便學習

 

而後下面是 另一種單例模式,懶漢模式優化

 

public class HelloSingleton {
    
    private static HelloSingleton w_Instance;

    //定義一個私有的構造函數,確保在該類的外部沒法生成類的實例
    private HelloSingleton(){
        
    }
    
    public static HelloSingleton getInst(){
        if(w_Instance == null){
            w_Instance = new HelloSingleton();
        }
        return w_Instance;
    }
}
public class HelloSingleton {
    
    private static HelloSingleton w_Instance;

    //定義一個私有的構造函數,確保在該類的外部沒法生成類的實例
    private HelloSingleton(){
        
    }
    
    public static HelloSingleton getInst(){
        if(w_Instance == null){
            w_Instance = new HelloSingleton();
        }
        return w_Instance;
    }
}

網上看到,或者大多數人都是如此寫懶漢模式的, 這種寫法在單線程環境下是安全的, 可是在多線程環境下 會形成生成多個實例的問題spa

好比現成A正在訪問 getInst()方法 ,線程A讀到w_Instance 爲null ,建立該類對象並返回,線程B正好在此時也訪問getInst方法,此時現成A構造的實例現成B沒法看見,由於多線程環境中非同步代碼快沒法保證共享變量的可見性。因此該寫法是有問題的, 調整爲以下則不會在多線程環境下出現建立多個實例的問題。

 1 public class HelloSingleton {
 2     
 3     private static HelloSingleton w_Instance;
 4 
 5     //定義一個私有的構造函數,確保在該類的外部沒法生成類的實例
 6     private HelloSingleton(){
 7         
 8     }
 9     
10     public static synchronized HelloSingleton getInst(){
11         if(w_Instance == null){
12             w_Instance = new HelloSingleton();
13         }
14         return w_Instance;
15     }
16 }
 1 public class HelloSingleton {
 2     
 3     private static HelloSingleton w_Instance;
 4 
 5     //定義一個私有的構造函數,確保在該類的外部沒法生成類的實例
 6     private HelloSingleton(){
 7         
 8     }
 9     
10     public static synchronized HelloSingleton getInst(){
11         if(w_Instance == null){
12             w_Instance = new HelloSingleton();
13         }
14         return w_Instance;
15     }
16 }

java用synchronized保證同步代碼快。 同步代碼快 既保證 變量的原子性,也保證變量的可見性。

 

上面是最簡單的兩種單例的寫法,可是爲了擴展 , 仍是介紹一些 其餘的 常見的單例的寫法。

 

effective   java做者 推崇的 用枚舉的方式實現的 singleton 

 

1 public enum HelloSingleton {
2     
3     Instance;
4     
5 }

額 你沒有看錯 就是這個樣子的  , 起初 看到這個代碼 , 我也很疑惑 , 這個是單例嗎, 可是確實它也實現了單例 模式。 java的枚舉不一樣於 c++ , c#等語言, java的枚舉是用對象實現的, 因此此枚舉裏 僅有一個對象

它的優勢是這麼介紹的 優勢:不只能避免多線程同步問題,並且還能防止反序列化從新建立新的對象

 

第四種單例,採用靜態內部類型, 個人同時  不少次 跟我講 他以爲java的內部類真的是很扯淡的設計, 不知道是幹什麼用的, 可是我我的感受java的內部類讓java 語言用起來更靈活, 好比我 不想讓別人使用的類 僅僅想在一個對象裏面使用的類 ,就能夠用private 定義一個 內部類 , 別人無須知道 內部實現。 更好的實現封裝的思想,

代碼示意圖以下

 

 1 public class HelloSingleton {
 2      private static class SingletonHolder
 3      {
 4          private final static HelloSingleton w_Instance = new HelloSingleton();
 5      }
 6      
 7      private HelloSingleton(){
 8          
 9      }
10      
11      public static HelloSingleton getInst(){
12          return SingletonHolder.w_Instance;
13      }
14 }

 

此類型看起來比較晦澀  好像繞了不燒 , 這樣寫的好處是:加載時不會初始化靜態變量INSTANCE,由於沒有主動使用,達到延遲加載

 

還有一個類型就不介紹了 ,由於我的 基本沒用到過,   感受本身最經常使用的就是第二種, 懶漢式 , 單例。

 

設計模式, 單例, 就是這麼簡單 。 

 

關於單例的變種你能夠這麼想 , 有的時候   你會想讓單例 生成指定數量的 實例, 具體實現就是在 類裏面加個 數量, 而後每次getInst 的時候去判斷 是否達到最大數量, 若是達到就不在生成新的實例 ,若是沒有,就生成新的實例返回, 好了 單例 就這麼簡單, 感受沒什麼好說的 就寫到這裏

相關文章
相關標籤/搜索