設計模式之-----單例模式

今天學習了單例模式,網上有一些講解,真心不錯,我在這裏歸納總結一下。

首先來說明一下什麼是單例模式,所謂單例模式,就體現在了這個“單”上,也就是說,在同一個JVM中,保證該類只有一個實例對象,這種模式在框架中用的很多,比如數據庫連接的時候,就大量使用了這個模式。

在來說說什麼時候使用,具體什麼時候使用,我覺得還要具體結合需求來定,一般而言,大量相似的重複操作,就沒必要每次都new一個對象出來,那樣不但浪費資源而且也不便於管理。比如我們做桌面程序的時候,要調出菜單,我們沒必要每次點擊都要new一個菜單,而是先判斷一下這個菜單有沒有被實例化,如果已經被實例化了,就直接返回,如果沒有被實例化,在去實例化也不遲。

下邊我來舉例說明一下如何實現單例模式

(以下代碼不是我自己寫的,是在網上看到寫的不錯了,與大家分享一下)

首先,單例模式在大體上可以分爲懶漢式,餓漢式

1、懶漢式,就是在第一次被人調用的時候去實例化自己,實現的方法是將構造方法私有化,然後提供一個public方法作爲實例對象的統一入口,在實例化之前先做判斷,如果已經實例化了,那麼直接返回即可,否則就新建一個對象。

注意:這種方式不是線程安全的

//懶漢式單例類.在第一次調用的時候實例化自己 
public class Singleton {
    private Singleton() {}
    private static Singleton single=null;
    //靜態工廠方法 
    public static Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
    }
}

針對懶漢式,有三種解決辦法去解決線程安全問題(針對上邊的例子改進)

(1)在實例化入口增加synchronized關鍵字

public static synchronized Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
}

(2)雙重檢查鎖定

public static Singleton getInstance() {
        if (singleton == null) {  
            synchronized (Singleton.class) {  
               if (singleton == null) {  
                  singleton = new Singleton(); 
               }  
            }  
        }  
        return singleton; 
    }

在這裏大家會有疑問,爲什麼會判斷兩次?大家仔細看第2行和第4行,兩個判斷一樣,是不是重複的呢?答案是不是的,我們可以假設一下,現在有兩個線程AB,都需要這個類,那麼他們就會調用這個實例化方法,第一次判斷的時候,兩個線程都可以通過第一次判斷,然後由於synchronized關鍵字,會有一個線程等待,一個線程執行,假設A先執行,執行完之後,這個類已經被實例化了,那麼B再去判斷的時候,因爲已經被A實例化了,那麼B就不會通過判斷,直接返回那個已經創建好的實例了。

(3)靜態內部類

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

這種方式實現了線程安全,在一定程度上也可以有很好的性能。


2、餓漢式

//餓漢式單例類.在類初始化時,已經自行實例化 
public class Singleton1 {
    private Singleton1() {}
    private static final Singleton1 single = new Singleton1();
    //靜態工廠方法 
    public static Singleton1 getInstance() {
        return single;
    }
}

這個方式不存在線程安全問題,因爲在類加載的時候就已經將類實例化了。而且由於final關鍵字的原因,這個實例不會被改變,所以種方式還是很方便的。


(以上代碼非個人原創,理解和說明爲本人所理解,在此聲明。)




發佈了78 篇原創文章 · 獲贊 18 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章