簡介
單例模式可以節省內存和計算,保證結果的正確.
方便管理
適用場景
- 無狀態的工具類
- 如日志工具類
- 全局信息類
- 如統計網站的訪問次數
優缺點:
優點:
- 在內存中只有一個對象,節省內存空間;
- 避免頻繁的創建銷毀對象,可以提高性能;
- 避免對共享資源的多重占用,簡化訪問;
- 為整個系統提供一個全局訪問點。
缺點:
- 不適用於變化頻繁的對象;
- 濫用單例將帶來一些負面問題,如為了節省資源將數據庫連接池對象設計為的單例類,可能會導致共享連接池對象的程序過多而出現連接池溢出;
- 如果實例化的對象長時間不被利用,系統會認為該對象是垃圾而被回收,這可能會導致對象狀態的丟失;
單例模式的多種寫法
餓漢式(靜態常量)
/**
* 好處:在類加載的時候便完成了實例化.
* */
public class singleton1 {
private static final singleton1 SINGLETON_1 = new singleton1();
private singleton1() {
}
public static singleton1 getInstance() {
return SINGLETON_1;
}
}
餓漢式(靜態代碼塊)
/**
* 好處:1.在類加載的時候便完成了實例化.
* 2.在初始化的時候可以進行一些屬性的初始化.
* */
public class singleton2 {
private static final singleton2 SINGLETON_2;
int anInt;
static {
// 可以從配置文件中去讀取一些值
SINGLETON_2 = new singleton2(1);
}
private singleton2(int anInt) {
this.anInt = anInt;
}
public static singleton2 getInstance() {
return SINGLETON_2;
}
}
枚舉
public enum Singleton3 {
INSTANCE_3;
public void whatever() {
}
}
懶漢式(線程不安全)
/**
* 好處:1.在需要的時候才回被創建,可以節約內存.
* */
public class singleton4 {
private static singleton3 SINGLETON;
private singleton4() {}
/**
* 線程不安全,不推薦使用
* */
public static singleton4 getInstance() {
if (SINGLETON == null) {
SINGLETON = new singleton3();
}
return SINGLETON;
}
}
懶漢式(線程安全)
/**
* 好處:1.線程安全
* 2.延遲加載
* 3.效率較高
* */
public class singleton5 {
private volatile static singleton4 SINGLETON;
private singleton5() {}
public static singleton5 getInstance() {
if (SINGLETON == null) {
synchronized (singleton5.class) {
if (SINGLETON == null) {
SINGLETON = new singleton4();
}
}
}
return SINGLETON;
}
}
靜態內部類
public class Singleton6 {
private Singleton6() {
}
private static class SingletonInstance {
private static final Singleton6 SINGLETON_6 = new Singleton6();
}
public static Singleton6 getInstance() {
return SingletonInstance.SINGLETON_6;
}
}
單例模式的最佳實踐
單例模式最好是使用枚舉類型去創建,這樣的好處就是既可以實現單例也可以面對序列化和反射操作時不受干擾.