在Java設(shè)計(jì)模式中,單例模式相對(duì)來說算是比較簡(jiǎn)單的一種構(gòu)建模式获洲。適用的場(chǎng)景在于:對(duì)于定義的一個(gè)類磨取,在整個(gè)應(yīng)用程序執(zhí)行期間只有唯一的一個(gè)實(shí)例對(duì)象。如Android中常見的Application對(duì)象畔乙。通過單例模式君仆,自行實(shí)例化并向這個(gè)系統(tǒng)提供這個(gè)單一實(shí)例的訪問方法。根據(jù)此單一實(shí)例產(chǎn)生的時(shí)機(jī)不同(當(dāng)然牲距,都是指第一次返咱,也是唯一一次產(chǎn)生此單一實(shí)例時(shí)),可以將其分為懶漢式牍鞠、餓漢式和登記式咖摹。
靜態(tài)成員變量屬于類所有,將該類對(duì)象設(shè)置為static难述,即可達(dá)到一定程度的唯一性萤晴,同時(shí)為了該類在內(nèi)存中只存在唯一一個(gè)對(duì)象吐句,需確保其構(gòu)造函數(shù)為私有的。通過一個(gè)公有的普通函數(shù)訪問其私有的構(gòu)造函數(shù)店读,返回一個(gè)靜態(tài)實(shí)例變量蕴侧。即可達(dá)到單例目的。
一两入、懶漢式:
其特點(diǎn)是延遲加載净宵,即當(dāng)需要用到此單一實(shí)例的時(shí)候,才去初始化此單一實(shí)例裹纳。
public class SingleTon {// 靜態(tài)實(shí)例變量
private static SingleTon instance;// 私有化構(gòu)造函數(shù)
private SingleTon() {}// 靜態(tài)public方法择葡,向整個(gè)應(yīng)用提供單例獲取方式
public static SingleTon getInstance() {if (instance == null) {instance = new SingleTon();}
return instance;}}
線程安全:
public class SingleTon {// 靜態(tài)實(shí)例變量加上volatile
private static volatile SingleTon instance;// 私有化構(gòu)造函數(shù)
private SingleTon() {}// 雙重檢查鎖
public static SingleTon getInstance() {
if (instance == null) {synchronized(Singleton.class){if(instance == null){instance = new SingleTon();}}}
return instance;}}
餓漢式:
餓漢式的特點(diǎn)是應(yīng)用中尚未需要用到此單一實(shí)例的時(shí)候即先實(shí)例化。
public class SingleTon {// 靜態(tài)實(shí)例變量剃氧,直接初始化
private static SingleTon instance = new SingleTon();// 私有化構(gòu)造函數(shù)
private SingleTon() {}// 靜態(tài)public方法敏储,向整個(gè)應(yīng)用提供單例獲取方式
public static SingleTon getInstance() {return instance;}}
登記式單例模式:
登記式單例模式,一般是通過一個(gè)專門的類對(duì)各單例模式的此單一實(shí)例進(jìn)行管理和維護(hù)朋鞍。通過Map方式可以方便的實(shí)現(xiàn)此中目的已添。常見的代碼如下:
import java.util.HashMap;
import java.util.Map;
public class SingleTonManager {
private static Map singleTonMap = new HashMap();
public static void main(String[] args) {// 獲取A類的單例
A a = (A) getInstance(A.class.getName());// 獲取B類的單例
B b = (B) getInstance(B.class.getName());}// 根據(jù)類型獲取單例
public static Object getInstance(String className) {
// 判斷singleTonMap中是否有此單例,有則取得后返回滥酥,無則添加單例后返回
if (!singleTonMap.containsKey(className)) {
try {singleTonMap.put(className, Class.forName(className).newInstance());} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();}}
return singleTonMap.get(className);}}
class A {}
class B {}
在多線程環(huán)境中更舞,以上各種方法構(gòu)造單例模式需要考慮到線程安全問題。
改進(jìn)型懶漢式(直接滿足線程安全)——通過靜態(tài)內(nèi)部類實(shí)現(xiàn)
在如上的懶漢單例模式中坎吻,對(duì)于多線程環(huán)境中缆蝉。可以通過常見的如synchronized等方式實(shí)現(xiàn)線程安全瘦真,同時(shí)刊头,可以通過Java靜態(tài)內(nèi)部類的方式實(shí)現(xiàn)進(jìn)一步改進(jìn)。
public class SingleTon {// 利用靜態(tài)內(nèi)部類特性實(shí)現(xiàn)外部類的單例
private static class SingleTonBuilder {private static SingleTon singleTon = new SingleTon();}
// 私有化構(gòu)造函數(shù)
private SingleTon() {}
public static SingleTon getInstance() {return SingleTonBuilder.singleTon;}
public static void main(String[] args) {SingleTon instance = getInstance();}}
其主要原理為:Java中靜態(tài)內(nèi)部類可以訪問其外部類的成員屬性和方法诸尽,同時(shí)原杂,靜態(tài)內(nèi)部類只有當(dāng)被調(diào)用的時(shí)候才開始首次被加載,利用此特性您机,可以實(shí)現(xiàn)懶漢式穿肄,在靜態(tài)內(nèi)部類中靜態(tài)初始化外部類的單一實(shí)例即可。