設計模式之單例模式

回顧概念:
Java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,我在這裏主要介紹兩種:懶漢式單例和餓漢式單例。
  單例模式有以下特點:
  1、單例類只能有一個實例。
  2、單例類必須自己創建自己的唯一實例。
  3、單例類必須給所有其他對象提供這一實例。
  單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。在計算機系統中,線程池、緩存、日誌對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。
一、懶漢模式
懶漢模式:類加載器在加載類的時候,不會創建實例,只有當需要創建對象的時候,纔會去創建類的實例。
1、最簡單的,但不是線程安全的懶漢模式。

public class Singleton {
    //私有化構造方法,防止外部使用new來創建對象。
    private Singleton () {}
    private static Singleton single = null;
    public static Singleton getInstance () {
        if(single == null) {
            single = new Singleton();
        }
        return single;
    }
}

2、線程安全的懶漢模式,但是實際運行中效果很差,類似數據庫中的表鎖。

public class Singleton {
    //私有化構造方法,防止外部使用new來創建對象。
    private Singleton () {}
    private static Singleton single = null;
    public static synchronized Singleton getInstance () {
        if(single == null) {
            single = new Singleton();
        }
        return single;
    }
}

3、雙重校驗鎖,類似數據庫中的行鎖

public class Singleton {
    //私有化構造方法,防止外部使用new來創建對象。
    private Singleton () {}
    //volatile關鍵字用於線程可見
    private static volatile Singleton single = null;
    public static Singleton getInstance () {
        if(single == null) {
            //鎖住類對象
            synchronized(Singleton.Class) {
                if(single == null) {
                    single = new Singleton();
                }
            }
        return single;
        }
    }
}

4、靜態內部類方法

public class Singleton {
    //私有化構造方法,防止外部使用new來創建對象。
    private Singleton () {}
    private static class LazyHolder {  
        //被final修飾的實例變量是無法被修改的,這就保證的對象的唯一性
       private static final Singleton single = new Singleton();  
    }  
    public static Singleton getInstance() {  
       return LazyHolder.single;  
    } 
}

二、餓漢模式
餓漢模式:類加載器加載的過程中,就已經創建好實例,因爲是在類加載初始階段就已經加載好了實例,所以餓漢模式總是線程安全的。
5、最簡單的,

public class Singleton {
    //私有化構造方法,防止外部使用new來創建對象。
    private Singleton () {}
    //被final修飾的實例變量是無法被修改的,這就保證的對象的唯一性
    private static final Singleton single =new Singleton();
    public static synchronized Singleton getInstance () {
        return single;
    }
}

6、與5同理,但是代碼實現方式不同

public class Singleton {
    //私有化構造方法,防止外部使用new來創建對象。
    private Singleton () {}
    //被final修飾的實例變量是無法被修改的,這就保證的對象的唯一性
    private static final Singleton single = null;
    //被static修飾的靜態代碼塊會在類加載期間,類加載器直接運行。
    static {
        single = new Singleton();
    }
    public static synchronized Singleton getInstance () {
        return single;
    }
}

總結:建議在選擇單例模式的時候選擇用雙重校驗鎖或靜態內部類的方式,這兩種方式能夠實現併發效率最優,但是當你確定某個類一定會被創建實例時,餓漢也是不錯的選擇。

參考博客:
JAVA設計模式之單例模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章