Java設計模式學習二

忘塵天外天發表於2017-11-01

Java設計思想之單例模式

  單例模式(Singleton Pattern)是Java中最常見的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。

  這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有的那個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。

  • 單例類只能有一個例項。
  • 單例類必須自己建立自己的唯一例項。
  • 單例類必須給所有其他物件提供這一例項。

  設計單例的意圖:保證一個類僅有一個例項,並提供一個訪問他的全域性訪問點。主要解決:一個全年局使用的類頻繁地建立和銷燬。控制例項數目,節省系統資源。判斷系統是否已經有這個單例,如果有則返回,如果沒有則建立。關鍵程式碼:建構函式是私有的。優點:在記憶體裡只有一個例項,減少記憶體的開銷,尤其是頻繁的建立和銷燬例項。避免對資源的多重佔用。缺點是:沒有介面,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來例項化。使用的場景:要求生產唯一序列號。計數器,不用每次重新整理都在資料庫里加一次,用單例先快取起來。建立一個物件需要消耗的資源過多,比如I/O與資料庫的連線等。注意:getInstance()方法中需要使用同步鎖synchronized防止多執行緒同時進入造成instance被多次例項化。

  單例型別的類建構函式是私有的,然後有一個本身的靜態例項。有一個靜態方法,供外界獲取它的靜態例項。

        public  class  SingleObject{
               
              //建立類的一個物件
              private   static  SingleObect  instnce  =  new  SingleObject() ;
             
             //私有建構函式,類不會被例項化
              private   SingleObject() {}   
                 
               //獲取唯一可用的物件
                public  static  SingleObject  getInstance(){
                      return  instance ;

                    }
}     

 單例模式的實現由多種方式:

1、懶漢式,執行緒不安全:Lazy初始化:是,多執行緒安全:否,實現難度:易。

描述:這種方式是最基本的實現方式,這種實現的最大問題就是不支援多執行緒。因為沒有加鎖synchronized,所以嚴格意義上並不算單例模式。這種方式lazy  loading很明顯,不要求執行緒安全,在多執行緒情況下不能正常工作。

        public  class  Singleton{
         private  static  Singleton  instance ;
        private Singleton(){}

       public  static Singleton  getInstance(){
                      
               if(instance == null){
                instance = new Singleton();

                   }
                return  instance ;

                   }

            }     

  下面幾種實現方式都支援多執行緒,但在效能上有所差異。

2、餓漢式:

lazy 初始化:否,多執行緒安全:是,實現難度:易。

描述:這種方式比較常用,但容易產生垃圾物件。優點:沒有執行效率會高。缺點:類載入時就初始化,浪費記憶體。它基於calssloder機制避免了多執行緒的同步問題,不過,instance在類載入時就例項化,雖然導致裝載的原因很多,在單例模式中大多數都是getInstance方法,但是也不能確定有其它的方式(或者其它的靜態方法導致類載入),這時初始化instance顯然沒有達到lazy loading的效果。

3、雙檢鎖/雙重校驗鎖(DCL,double-checked  locking)

lazy初始化:是,多執行緒安全:是,實現難度:較複雜。描述:這種方式採用雙鎖機制,安全且在多執行緒情況下保持高效能。getInstance()的效能對應用程式很關鍵。

        public  class Singleton{
    
         private  volatile  static  Singleton  singleton ;
         private  Singleton(){}
          public  static  Singleton  getSingleton(){
         if(singleton == null){
               synchronized (Singleton.class){
                  
                   if(singleton == null){

                        singleton = new Singleton();
                   }
                  }
             }     
                return singleton ;    
         } 
     }            

 5、登記式/靜態內部類

Lazy初始化:是,多執行緒安全:是,實現難度:一般。描述:這種方式能達到雙檢鎖一樣的功效,但實現更簡單。對靜態域使用延遲初始化,應使用這種方式二不是雙檢鎖方式。這種方式只適用於靜態域的情況,雙檢鎖方式可在例項域需要延遲初始化時使用。這種方式同樣利用了classloder機制來保證初始化instance時只有一個執行緒,它跟第三種方式不同之處:第3中方式只要Singleton類被裝載了,instance救護被例項化(沒有達到lazy loading效果),而這種方式是Singleton類被裝載了,instance不一定被初始化。因為SingletonHolder類沒有被主動使用,只有顯式通過呼叫getInstance方法時,才會顯式裝載SingletonHolder類,從而例項化instance。

  

        public  class Singleton{
          private  static class SingletonHolder{
           private static  final Singleton  INSTANCE = new Singleton();
           }
        
           private Singleton(){}
           private static final Singleton  getInstance (){
                return  SingletonHolder.INSTANCE ;           
             }
        }    

  

相關文章