簡介
單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。在計算機系統中,任務管理器、線程池、緩存、日誌對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。在項目當中,系統啓動讀取配置文件就需要單例保證配置的一致性。
要點與實現
要點
- 一是某個類只能有一個實例
- 二是它必須自行創建這個實例
- 三是它必須自行向整個系統提供這個實例
實現
- 一是單例模式的類只提供私有的構造函數
- 二是類定義中含有一個該類的靜態私有對象,
- 三是該類提供了一個靜態的公有的函數用於創建或獲取它本身的靜態私有對象。
實現單例模式方式
- 餓漢式
/** 餓漢式單例模式*/
public class Singleton {
private Singleton(){}//私有構造器
/*
* JVM只爲靜態分配一次內存,在加載類的過程中
* 完成靜態變量的內存分配,天然的是線程安全的
*/
private static Singleton singleton=new Singleton();
public static Singleton getInstance(){//靜態工廠方法
return singleton;
}
}
- 懶漢式
/** 懶漢式單例模式*/
public class Singleton {
private Singleton(){}//私有構造器
private static Singleton singleton=null;//靜態變量
/**
* 延遲加載,需要的時候初始化,方法加鎖,併發效率低
*/
public static synchronized Singleton getInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
- 雙重鎖(餓漢式變種)
/**雙重鎖單例模式*/
public class Singleton {
private Singleton(){}//私有構造器
private static Singleton singleton=null;//靜態變量
/**
* 避免整個方法被鎖,只對需要鎖的代碼部分加鎖,可以提高執行效率。
*/
public static Singleton getInstance(){
if(singleton==null){
synchronized (Singleton.class){
if(singleton==null){
singleton=new Singleton();
}
}
}
return singleton;
}
}
- 靜態內部類實現
/**靜態內部類模式*/
public class Singleton {
private Singleton(){}//私有構造器
private static class SingletonClassInstance{
//static final 保證對象只會被賦值一次
private static final Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonClassInstance.instance;
}
}
- 靜態代碼塊實現
/**靜態代碼塊實現**/
public class Singleton {
private Singleton(){}//私有構造器
private static Singleton singleton=null;//靜態變量
//靜態代碼塊
static {
singleton=new Singleton();
}
public static Singleton getInstance(){
return singleton;
}
}
- 枚舉類實現
/*枚舉的單例模式*/
public class Singleton {
private Singleton (){}//私有構造
public static Singleton getInstance(){
return SingletonEnum.INSTANCE.getInstance();
}
/*目前最爲安全的實現單例的方法是通過內部靜態enum的方法來實現,
*因爲JVM會保證enum不能被反射並且構造器方法只執行一次。*/
private enum SingletonEnum{
INSTANCE;
private Singleton singleton;
//JVM會保證此方法絕對只調用一次
private SingletonEnum(){
singleton=new Singleton();
}
public Singleton getInstance(){
return singleton;
}
}
}
反射攻擊示例