單例模式注意事項 和 細(xì)節(jié)說明
- 單例模式保證了 系統(tǒng)內(nèi)存中該類只存在一個對象拉宗,節(jié)省了系統(tǒng)資源,對于一些需要頻繁創(chuàng)建銷毀的對象匣掸,使用單例模式可以提高系統(tǒng)性能
- 當(dāng)想實例化一個單例類的時候霞揉,必須要記住使用相應(yīng)的獲取對象的方法,而不是使用 new
- 單例模式使用的場景:需要頻繁的進(jìn)行創(chuàng)建和銷毀的對象般又、創(chuàng)建對象時耗時過多或耗費資源過多(即:
重量級對象
),但又經(jīng)常用到的對象巍佑、工具類對象
倒源、頻繁訪問數(shù)據(jù)庫或文件的對象(比如數(shù)據(jù)源、session 工廠
等)
單例模式有五種方式:
餓漢式(靜態(tài)常量)
【推薦】- 懶漢式(線程安全句狼,同步方法)效率低
雙重檢查
【推薦】靜態(tài)內(nèi)部類
【推薦】枚舉
【推薦】
餓漢式【推薦】
/**
* 餓漢式單例在類創(chuàng)建的同時就已經(jīng)創(chuàng)建好一個靜態(tài)的對象供系統(tǒng)使用,以后不再改變
* 所以是線程安全的热某,可以直接用于多線程而不會出現(xiàn)問題腻菇。
* 【基于JVM的類加載器機(jī)制 避免了多線程的同步問題,對象在類裝載時就實例化】
*/
public class Hungry {
private final static Hungry HUNGRY = new Hungry();
//單例模式要保證構(gòu)造器私有化昔馋,避免有人New對象
private Hungry() {}
public static Hungry getInstance() {
return HUNGRY;
}
}
懶漢式【不推薦】
/**
* 線程安全筹吐,同步方法,但是效率很低【不推薦使用】
*/
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
雙重檢查【推薦】
/**
* 單例模式(雙重檢查)
* 實現(xiàn)懶加載秘遏,采用雙鎖機(jī)制丘薛,安全且在多線程情況下能保持高性能。
* volatile:1邦危、保證數(shù)據(jù)可見性 2洋侨、防止指令重排
*/
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
靜態(tài)內(nèi)部類【推薦】
/**
* 單例模式(靜態(tài)內(nèi)部類)
* 懶加載,且利用JVM類加載機(jī)制保證了線程安全
*/
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private final static Singleton2 SINGLETON = new Singleton2();
}
public static Singleton getInstance(){
return SingletonInstance.SINGLETON;
}
}
枚舉【推薦】
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
單例模式的優(yōu)點和缺點
單例模式的優(yōu)點:
單例模式可以保證內(nèi)存里只有一個實例倦蚪,減少了內(nèi)存的開銷希坚。
可以避免對資源的多重占用。
單例模式設(shè)置全局訪問點陵且,可以優(yōu)化和共享資源的訪問裁僧。單例模式的缺點:
單例模式一般沒有接口,擴(kuò)展困難。如果要擴(kuò)展聊疲,則除了修改原來的代碼茬底,沒有第二種途徑,違背開閉原則获洲。
在并發(fā)測試中阱表,單例模式不利于代碼調(diào)試。在調(diào)試過程中昌妹,如果單例中的代碼沒有執(zhí)行完捶枢,也不能模擬生成一個新的對象。
單例模式的功能代碼通常寫在一個類中飞崖,如果功能設(shè)計不合理烂叔,則很容易違背單一職責(zé)原則。