适用場景:
1、 需要生成唯一序列的環境;
2、 需要頻繁執行個體化然後銷毀的對象;
3、 建立對象時耗時過多或者耗資源過多,但又經常用到的對象;
4、 友善資源互相通信的環境。
Java 單例模式有五種實作方式:
一、 餓漢式:
特點:線程安全,調用效率高,但是不能延時加載。
示例代碼:
public class SingletonOne {
//第2步,用一個私有的靜态變量來存自身
//執行個體化自身SingletonOne這個類。final保證安全
private static final SingletonOne INSTANCE=new SingletonOne();
//第1步、隐藏(私有)構造器
private SingletonOne(){
}
//第3步,建立靜态工廠方法 ,讓外部可以擷取執行個體(INSTANCE)
public static SingletonOne getInstance(){
return INSTANCE;
}
}
二、 懶漢式:
特點:線程安全,調用效率不高,但是能延時加載
示例代碼:
public class SingletonTwo {
//類初始化時,不初始化這個對象(延時加載,真正用的時候再建立)
private static SingletonTwo instance;
// 私有化構造器
private SingletonTwo() {
}
//synchronized方法同步,調用效率低
// 建立靜态工廠方法 ,讓外部可以擷取執行個體,需要用的時候才會new
public static synchronized SingletonTwo getInstance() {
if (instance == null) {
instance = new SingletonTwo();
}
return instance;
}
}
三、 Double CheckLock實作單例:
Double CheckLock也就是雙重鎖判斷機制(由于JVM底層模型原因,偶爾會出問題,不建議使用),是在懶漢式單例上發展而來
示例代碼:
public class SingletonThree {
private volatile static SingletonThree instance;
//私有化構造器
private SingletonThree() {
}
//靜态工廠方法,雙重鎖判斷機制
public static SingletonThree newInstance() {
if (instance == null) {
synchronized (SingletonThree.class) {
if (instance == null) {
instance = new SingletonThree();
}
}
}
return instance;
}
}
四、 靜态内部類模式:
特點:線程安全,調用效率高,可以延時加載
示例代碼:
public class SingletonFour {
// 靜态内部類
private static class SingletonClassInstance {
private static final SingletonFour instance = new SingletonFour();
}
// 私有化構造器
private SingletonFour() {
}
//靜态工廠方法
public static SingletonFour getInstance() {
return SingletonClassInstance.instance;
}
}
五、 枚舉類:
特點:線程安全,調用效率高,不能延時加載,可以天然的防止反射和反序列化調用
示例代碼:
public class SingletonFive {
//私有化構造器
private SingletonFive(){
}
//使用枚舉
private static enum Singleton{
INSTANCE;
private SingletonFive singleton;
//JVM會保證此方法絕對隻調用一次
private Singleton(){
singleton = new SingletonFive();
}
public SingletonFive getInstance(){
return singleton;
}
}
//靜态工廠方法
public static SingletonFive getInstance(){
return Singleton.INSTANCE.getInstance();
}
}
注意:如何選擇?
單例對象占用資源少,不需要延時加載時:枚舉好于餓漢;
單例對象占用資源多,需要延時加載時:靜态内部類好于懶漢式。
總結:
單例對象(Singleton)是一種常用的設計模式。在Java應用中,單例對象能保證在一個JVM中,該對象隻有一個執行個體存在。
餓漢式單例:直接将對象定義出來;
懶漢式單例:隻給出變量,并不将其初始化(先定義,但是不建立對象)。
單例模式解決的問題:保證一個類在記憶體中的對象唯一性。
比如:多程式讀取一個配置檔案時,建議配置檔案封裝成對象。會友善操作其中資料,又要保證多個程式讀到的是同一個配置檔案對象,就需要該配置檔案對象在記憶體中是唯一的。
Runtime()方法就是單例設計模式進行設計的。
如何保證對象唯一性呢?
思想:
1,不讓其他程式建立該類對象。
2,在本類中建立一個本類對象。
3,對外提供方法,讓其他程式擷取這個對象。
步驟:
1,因為建立對象都需要構造函數初始化,隻要将本類中的構造函數私有化,其他程式就無法再建立該類對象;
2,就在類中建立一個本類的對象;
3,定義一個方法,傳回該對象,讓其他程式可以通過方法就得到本類對象。(作用:可控)
代碼展現:
1,私有化構造函數;
2,建立私有并靜态的本類對象;
3,定義公有并靜态的方法,傳回該對象。