單例模式屬於建立型模式,保證在程式執行期間乙個類只有乙個例項,並提供乙個全域性訪問點推薦訪問我的個人**,排版更好看呦:
什麼是單例模式
單例模式目的是保證在程式執行期間乙個類只有乙個例項,並提供乙個全域性訪問點,無論什麼情況下,只會生成乙個例項,免去繁瑣的建立銷毀物件的過程。
如何設計單例
如何設計單例模式其實很簡單,只需要考慮乙個問題,例項是否可以保證是全域性唯一,只要滿足這個條件,這個單例設計的肯定就合格了。
關於例項是否可以保證是全域性唯一的延伸出的問題:
是否執行緒安全,不安全肯定就不能保證全域性只有乙個例項
是否支援序列化,支援序列化的類,被反序列化之後肯定就不是全域性唯一了
是否支援反射,支援反射肯定也不是全域性唯一的
是否可以被轉殖,這個也不能保證全域性唯一
所以設計乙個安全的單例需要考慮的問題還是很多的。
針對上述問題常見的解決辦法:
保證執行緒安全,使用volatile+synchronized實現
防止序列化攻擊,重寫readresolve方法
防止反射,常用的方案是在單例類裡增加乙個boolean型別的flag標識,在例項化的時候先判斷flag標識
防止轉殖,重寫clone()方法
實現乙個最簡單的單例就需要考慮到以上的所有問題,這個時候什麼有用的方法還沒寫那,**就已經很多了,那有沒有簡單的辦法既滿足上述條件,**又簡潔那,那肯定有,使用列舉實現單例。
常見的單例模式設計方案
常見的單例模式設計方案大概有五種,懶漢模式,餓漢模式,雙重檢查方式實現,靜態內部類實現,列舉實現。
簡單的分個類:
是否支援延遲載入,分為懶漢模式和餓漢模式
執行緒安全設計了雙重檢查模式實現,靜態內部類實現方式
不支援序列化,反射,轉殖,列舉實現方式
其中懶漢模式,餓漢模式,雙重檢查方式實現,靜態內部類的實現方式都可以概括為以下兩步:
建構函式私有化,保證在外部無法new物件
提供乙個static方法獲取當前例項(不同方案,實現不同)
當然列舉的實現方式最簡單,也最安全的,所以推薦使用列舉實現,其次推薦使用靜態內部類方式實現。
餓漢模式
不是延遲載入,載入類的時候直接初始化
/**
* @auther: chenmingyu
* @date: 2019/2/12 16:26
* @description:
*/public class singleton
public static singleton getinstance()
}
優點:執行緒安全,**簡單。
缺點:不是延遲載入,如果你用不到這個類,它也會例項化,還有乙個問題就是如果這個例項依賴外部一些配置檔案,引數什麼的,在例項化之前就要獲取到,否則就例項化異常
懶漢模式
延遲載入,首次需要使用的時候在例項化,需要考慮執行緒安全
執行緒不安全的實現方式
public class singleton
public static singleton getinstance()
return singleton;
}}
雙重檢查(dcl:double check lock)
執行緒安全的實現方式:
public class singleton
public static singleton getinstance()}}
return singleton;
}}
面試官:為什麼使用volatile修飾singleton變數?
說的volatile,首先肯定回答volatile的可見性
防止重排序優化,如果不用volatile修飾,多執行緒的情況下,可能會出現執行緒a進入synchronized**塊,執行new singleton();,首先給singleton分配記憶體,但是還沒有初始化變數,這時候執行緒b進入getinstance方法,進行第乙個判斷,此時singleton已經不為空,直接返回singleton,然後肯定報錯。使用volatile修飾之後禁止jvm重排序優化,所以就不會出現上面的問題
靜態內部類實現
使用靜態內部類實現也是延遲載入,利用靜態內部類去實現執行緒安全,只有在第一次呼叫getinstance方法的時候才會去載入singletonholder,初始化singleton
public class singleton
public static singleton getinstance()
private static class singletonholder
}
列舉實現
列舉實現**更簡潔,執行緒安全,並且保證列舉不會被反序列化,反射和轉殖
/**
* @auther: chenmingyu
* @date: 2019/2/12 16:30
* @description:
*/public enum singleton
}
所以推薦使用列舉方式,呼叫singleton.singleton.method(); 23種設計模式之單例模式
我們也經常遇到類似的情況,為了節約系統資源,有時需要確保系統中某個類只有唯一乙個例項,當這個唯一例項建立成功之後,我們無法再建立乙個同型別的其他物件,所有的操作都只能基於這個唯一例項。為了確保物件的唯一性,我們可以通過單例模式來實現,這就是單例模式的動機所在。定義 單例模式 singleton pa...
23種設計模式之 單例模式
保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。讓類自身負責儲存它的唯一例項,這個類可以保證沒有其他例項可以被建立,並且它可以提供乙個訪問 獲取 該例項的方法。單例類應滿足以下特點 單例類 singleton 自己例項化自己的唯一例項,並提供訪問該唯一例項的方法。public class s...
23種設計模式之單例模式
單例模式 確保乙個類最多只有乙個例項,並提供乙個全域性訪問點 普通單例模式示例 有問題 public class singleton public static singleton getinstance return uniqueinstance 示例singleton public class ...