單例模式,學習筆記
阿新 • • 發佈:2020-07-30
一、單例模式實現三要素:
●只能有一個例項。
◆構造器私有化
●自行建立這個例項
◆含有一個該類的靜態變數來儲存這個唯一的例項
●必須自行向整個系統提供這個例項;
◆對外提供獲取該例項物件的方式:
(1)直接暴露
(2)用靜態變數的get方法獲取
二、單例模式分類
根據物件建立的時機不同,單例模式可以分為兩類。一種是在類初始化的時候直接建立物件,稱為餓漢式;另一種是在呼叫類靜態方法時才建立物件,稱為懶漢式。
三、餓漢式
餓漢式是執行緒安全的。
1.直接例項化餓漢式
public class Singleton { public static final Singleton INSTANCE = newSingleton(); //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 propertiesView Code= 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; } }
四、懶漢式
方式一:
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例項物件。
靜態內部類不會自動隨著外部類的載入和初始化而初始化,它是要單獨去載入和初始化的。因為是在內部類載入和初始化時,建立的,因此是執行緒安全的。