設(shè)計(jì)模式-單例模式

在Java設(shè)計(jì)模式中,單例模式相對來說算是比較簡單的一種構(gòu)建模式。適用的場景在于對于定義的一個(gè)類,在整個(gè)應(yīng)用程序執(zhí)行期間只有唯一的一個(gè)實(shí)例對象。如Android中常見的Application對象。通過單例模式,自行實(shí)例化并向這個(gè)系統(tǒng)提供這個(gè)單一實(shí)例的訪問方法。根據(jù)此單一實(shí)例產(chǎn)生的時(shí)機(jī)不同(當(dāng)然,都是指第一次,也是唯一一次產(chǎn)生此單一實(shí)例時(shí)),可以將其分為懶漢式、餓漢式和登記式。

靜態(tài)成員變量屬于類所有,將該類對象設(shè)置為static,即可達(dá)到一定程度的唯一性,同時(shí)為了該類在內(nèi)存中只存在唯一一個(gè)對象,需確保其構(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è)專門的類對各單例模式的此單一實(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)

在如上的懶漢單例模式中,對于多線程環(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í)例即可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容