1. 程式人生 > 實用技巧 >單例模式,學習筆記

單例模式,學習筆記

一、單例模式實現三要素:

●只能有一個例項。
  ◆構造器私有化

●自行建立這個例項
  ◆含有一個該類的靜態變數來儲存這個唯一的例項
●必須自行向整個系統提供這個例項;
  ◆對外提供獲取該例項物件的方式:
  (1)直接暴露

  (2)用靜態變數的get方法獲取

二、單例模式分類

根據物件建立的時機不同,單例模式可以分為兩類。一種是在類初始化的時候直接建立物件,稱為餓漢式;另一種是在呼叫類靜態方法時才建立物件,稱為懶漢式。

三、餓漢式

餓漢式是執行緒安全的。

1.直接例項化餓漢式

public class Singleton {
    public static final Singleton INSTANCE = new
Singleton(); //final修飾,強調這是一個單例 private Singleton(){} }

2.列舉類餓漢式

public enum Singleton {
    INSTANCE;
}

3.靜態程式碼塊方式

public class Singleton {
    public static final Singleton INSTANCE;  //final修飾,強調這是一個單例
    static {
        INSTANCE = new Singleton();
    }
    private Singleton(){}

}

這種方式適合於需要通過載入外部檔案,來例項化單例物件屬性的時候。

例如:

public class Singleton1 {
    public static final Singleton1 INSTANCE;
    private String name;
    
    static {
        INSTANCE = new Singleton1();
        try {
            InputStream inputStream = Singleton1.class.getClassLoader().getResourceAsStream("singleton.properties");
            Properties properties 
= new Properties(); properties.load(inputStream); String name = properties.getProperty("singleton1.name"); INSTANCE.name = name; } catch (IOException e) { e.printStackTrace(); } } private Singleton1(){} public String getName() { return name; } }
View Code

四、懶漢式

方式一:

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

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

注:此方式有執行緒安全問題,只適用於單執行緒環境。

方式二:同步程式碼塊

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

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

注:此方式雖然解決了執行緒安全問題,但是效率低,不推薦使用

方式三:

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

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

效率比前一種高,推薦使用

方式四:靜態內部類(強烈推薦使用)

public class Singleton {
    private Singleton(){

    }

    private static class Inner{
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){
        return Inner.INSTANCE;
    }
}

注:

在內部類被載入和初始化時,才建立工 NSTANCE例項物件。

靜態內部類不會自動隨著外部類的載入和初始化而初始化,它是要單獨去載入和初始化的。因為是在內部類載入和初始化時,建立的,因此是執行緒安全的。