單例模式是最簡(jiǎn)單的設(shè)計(jì)模式 , 甚至在學(xué)校中就可以學(xué)到 , 也是很多初級(jí)程序員(比如我)會(huì)的唯一的設(shè)計(jì)模式.那么這種設(shè)計(jì)模式有什么用呢 , 具體怎么實(shí)現(xiàn)?
基礎(chǔ)概念
- 因?yàn)閮?nèi)存原因 , 希望整個(gè)系統(tǒng)只有一個(gè)全局對(duì)象, 有利于對(duì)整個(gè)系統(tǒng)的協(xié)調(diào)管理 , 比如SharedPreference , 構(gòu)造多個(gè)實(shí)例過(guò)于浪費(fèi)
- 定義:一個(gè)類只有一個(gè)實(shí)例 , 并向整個(gè)系統(tǒng)提供
關(guān)鍵點(diǎn)
- 構(gòu)造函數(shù)不開放
- 通過(guò)靜態(tài)方法來(lái)返回對(duì)象
- 單例類有且只有一個(gè)
單例模式的幾種實(shí)現(xiàn)
1. 餓漢式
public class TestTwo {
// 在初始化靜態(tài)變量時(shí)就創(chuàng)建對(duì)象 , 會(huì)在初始化時(shí)候稍慢一些
private static TestTwo instance=new TestTwo();
private TestTwo(){
}
public static TestTwo getInstanceHunger(){
return instance;
}
}
2. 飽漢式
public class TextOne {
private static TextOne instance;
private TextOne(){
}
// 在使用該方法時(shí)才開始創(chuàng)建對(duì)象
public static synchronized TextOne getInstanceFull(){
if (instance==null){
instance=new TextOne();
}
return instance;
}
}
使用TestOne.getInstance()方法是才會(huì)開始創(chuàng)建對(duì)象 , 對(duì)于并發(fā)不是很高的類 , 這種方法完全沒有問題 .但是在高并發(fā)下會(huì)創(chuàng)建多個(gè)實(shí)例 , 失去單例的意義
3. DLC模式
public class TestThree {
private volatile static TestThree instance=null;
private TestThree(){
}
public static TestThree getInstance(){
if (instance==null){ //避免不必要的同步
synchronized (TestThree.class){
if (instance==null){ // 驗(yàn)證賦值
instance=new TestThree();
}
}
}
return instance;
}
}
首先在這里加入了兩個(gè)判斷 , 第一層是為了避免不必要的同步, 第二層是為了在null的情況下獲取實(shí)例.
然后要注意volatile關(guān)鍵字, 在讀取volatile類型的變量時(shí)總會(huì)返回最新寫入的值, 所以即使發(fā)生了指令亂序 , 也不會(huì)干擾到instance的賦值 .
4. 靜態(tài)內(nèi)部類
public class TestFour {
private TestFour(){}
public static TestFour getInstance(){
return SingletonHolder.instance;
}
// 內(nèi)部類
private static class SingletonHolder{
private static final TestFour instance=new TestFour();
}
}