單例模式概述
滾滾歷史拧廊,朝代不斷更迭监徘,但卻存在著永恒定律,比如一個朝代皇帝無論怎么更換吧碾,有且只有一個凰盔,而對于軍隊而言,最高指揮官也是只有一個滤港,因為一山不容二虎廊蜒。
而在計算機系統(tǒng)中趴拧,無論打印機有多少溅漾,我們的打印機后臺處理程序也只有一個,包括其他的像驅(qū)動程序著榴、線程池添履、緩存、日志等脑又,在實際的軟件應(yīng)用當(dāng)中暮胧,很多時候我們都會需要它有且只有唯一的一個實例在工作。
針對這種我們只需要某種類型在特定的場合下只有唯一實例產(chǎn)生工作的場景问麸,就可以使用單例模式來實現(xiàn)往衷。
目的:使得類的一個對象成為該類系統(tǒng)中的唯一實例
定義:一個類有且僅有一個實例,并且自行實例化向整個系統(tǒng)提供
要點
- 某個類只能有一個實例
- 必須自行創(chuàng)建實例
- 必須自行向整個系統(tǒng)提供這個實例
實現(xiàn)
- 只提供私有的構(gòu)造方法
- 含有一個該類的靜態(tài)私有對象
- 提供一個靜態(tài)的公有方法用于創(chuàng)建严卖、獲取靜態(tài)私有對象
單例模式實現(xiàn)
代碼實現(xiàn)方案:餓漢式與懶漢式
餓漢式
//餓漢式:創(chuàng)建對象實例的時候直接初始化 空間換時間
public class SingletonOne {
//1席舍、創(chuàng)建類中私有構(gòu)造
private SingletonOne(){
}
//2、創(chuàng)建該類型的私有靜態(tài)實例
private static SingletonOne instance=new SingletonOne();
//3哮笆、創(chuàng)建公有靜態(tài)方法返回靜態(tài)實例對象
public static SingletonOne getInstance(){
return instance;
}
}
懶漢式
//懶漢式:類內(nèi)實例對象創(chuàng)建時并不直接初始化来颤,直到第一次調(diào)用get方法時,才完成初始化操作
//時間換空間
public class SingletonTwo {
//1稠肘、創(chuàng)建私有構(gòu)造方法
private SingletonTwo(){
}
//2福铅、創(chuàng)建靜態(tài)的該類實例對象
private static SingletonTwo instance = null;
//3、創(chuàng)建開放的靜態(tài)方法提供實例對象
public static SingletonTwo getInstance(){
if(instance==null){
instance=new SingletonTwo();
}
return instance;
}
}
測試
public class Test {
public static void main(String[] args) {
//餓漢式
SingletonOne one = SingletonOne.getInstance();
SingletonOne two = SingletonOne.getInstance();
System.out.println(one == two); //true
//懶漢式
SingletonTwo one1 =SingletonTwo.getInstance();
SingletonTwo two1=SingletonTwo.getInstance();
System.out.println(one1 == two1); //true
}
}
餓漢式 vs 懶漢式
- 餓漢式在類加載時就創(chuàng)建實例项阴,第一次加載速度快滑黔,空間換時間
懶漢式第一次使用時才進(jìn)行實例化,第一次加載速度慢环揽,時間換空間
- 餓漢式線程安全略荡,懶漢式存在線程風(fēng)險
解決方案:a.同步鎖 b.雙重校驗鎖 c.靜態(tài)內(nèi)部類 d.枚舉
單例模式總結(jié)
優(yōu)點
- 在內(nèi)存中只有一個對象,節(jié)省內(nèi)存空間
- 避免頻繁的創(chuàng)建銷毀對象,提高性能3、避免對共享資源的多重占用
缺點
- 擴展比較困難
- 如果實例化后的對象長期不利用薯演,系統(tǒng)將默認(rèn)為垃圾進(jìn)行回收撞芍,造成對象狀態(tài)丟失
適用場景
- 創(chuàng)建對象時占用資源過多,但同時又需要用到該類對象
- 對系統(tǒng)內(nèi)資源要求統(tǒng)一讀寫跨扮,如讀寫配置信息
- 當(dāng)多個實例存在可能弓|起程序邏輯錯誤序无,如號碼生成器