單例模式指一個類在它的生命週期內只會存在一個實例,通常被用於無狀態的類。實現單例模式有3種方法(其實有更多種,Effective Java列出3種):
1、public final static成員變量
public static final Rule3 INSTANCE= new Rule3();
Private Rule3() { }
2、靜態工廠
private static final Rule3 INSTANCE = new Rule3();
private Rule3() { }
public static Rule3 getInstance() { return INSTANCE; }
3、枚舉
public enum Rule3{
INSTANCE;
private Rule3() {
//do something
}
}
優點1:簡單
3種方法都非常簡單、容易實現。
優點2:安全都是餓漢式單例模式,能夠保證線程安全。尤其枚舉方式實現的單例,無償地提供了序列化機制,絕對防止多次實例化,即使是在面對複雜的序列化或者反射攻擊的時候。
缺點1:不支持懶加載
3種方法都是先進行實例化,無論你是否使用到這個類。當然,這點缺點影響不大,如果是實例化帶來資源消費非常大的場景,可能要考慮懶漢式單例模式。
帶volatile雙重判空懶漢式//volatile防止指令重排
private static volatile Rule3 instance;
private Rule3() {}
public static Rule3 getInstance() {
//當實例不為空時,線程不會進入同步塊
if (instance == null) {
synchronized (Rule3.class) {
//避免第2個線程進入同步塊時進行實例化
if (instance == null) {
instance = new Rule3();
}
}
}
return instance;
}
最佳實踐
使用Spring框架時,默認bean實例化是註冊登記式單例,每使用一次,都往一個固定的容器中去註冊並且將使用過的對象進行緩存,下次去取對象的時候,就直接從緩存中取值,以保證每次獲取的都是同一個對象,不需要自己去實現單例了。非Spring場景下,可以考慮帶volatile雙重判空懶漢式或者枚舉方式實現單例。
專業從事軟件研發工作多年,在軟件設計、開發、測試、研發管理等領域裡經驗豐富,感興趣的朋友可以關注我的頭條號,相信一定會有所收穫。如果有軟件研發方面的問題,可以諮詢我。謝謝!