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

創(chuàng)建型模式(Creational Pattern)

單例模式(SingleTon)

第一種UML圖


第二種UML圖


單例模式的寫法有多種寫法,主要介紹三種:懶漢式單例,餓漢式單例,登記式單例

單例有以下特點(diǎn):

1.單例類只有一個(gè)實(shí)例

2.單例類必須自己創(chuàng)建自己的唯一對(duì)象

3.單例類必須給所有其他對(duì)象提供這一實(shí)例

單例模式確保某個(gè)類只有一個(gè)實(shí)例對(duì)象,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例.在計(jì)算機(jī)系統(tǒng)中,線程池,緩存,日志對(duì)象,對(duì)話框,打印機(jī),顯卡就驅(qū)動(dòng)對(duì)象都是常見的單例,這些應(yīng)用都或多或少的具有資源管理器的功能.每臺(tái)計(jì)算機(jī)可以若干個(gè)打印機(jī),但是只有一個(gè)Printer Spooler,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)中,每臺(tái)計(jì)算機(jī)可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個(gè)通信端口同時(shí)被兩個(gè)請(qǐng)求同時(shí)調(diào)用.總之,選擇單例模式就是為了避免不一致的狀態(tài).

一.懶漢模式單例

//懶漢式單例類.在第一次調(diào)用的時(shí)候?qū)嵗约?

public class Singleton {?

? ? private Singleton() {}?

? ? private static Singleton single=null;?

? ? //靜態(tài)工廠方法?

? ? public static Singleton getInstance() {?

? ? ? ? if (single == null) {? ?

? ? ? ? ? ? single = new Singleton();?

? ? ? ? }? ?

? ? ? ? return single;?

? ? }?

}


SingleTon通過(guò)將構(gòu)建方法限定為private避免了類在外部的實(shí)例化,在用一個(gè)虛擬機(jī)的范圍內(nèi),Singleton的唯一實(shí)例只能通過(guò)getInstance()方法訪問(wèn)

但是以上懶漢式的實(shí)現(xiàn)沒有考慮縣城安全問(wèn)題,他是縣城不安全的,并發(fā)環(huán)境下很有可能出現(xiàn)多個(gè)SingleTon實(shí)例,要實(shí)現(xiàn)線程安全,有一下三種方式,都是對(duì)getInstance方法的構(gòu)造,保證了懶漢式單例的線程安全,如果你第一次接觸單例模式,對(duì)線程安全不是很了解,可以先跳過(guò)下面的這三小條,去看餓漢式單例,等看完后面的再回頭考慮線程安全問(wèn)題:

1.getInstance方法上加同步

publicstaticsynchronized Singleton getInstance() {

? ? ? ? ? ? if(single ==null) {? ?

? ? ? ? ? ? ? ? single =new Singleton();?

? ? ? ? ? ? }? ?

? ? ? ? ? ? return single;?

? ? }

2.雙重檢查鎖定

public static Singleton getInstance() {

? ? ? ? if (singleton == null) {? ?

? ? ? ? ? ? synchronized (Singleton.class) {? ?

? ? ? ? ? ? ? if (singleton == null) {? ?

? ? ? ? ? ? ? ? ? singleton = new Singleton();?

? ? ? ? ? ? ? }? ?

? ? ? ? ? ? }? ?

? ? ? ? }? ?

? ? ? ? return singleton;?

? ? }

3.靜態(tài)內(nèi)部類

public class Singleton {

? ? private static class LazyHolder {? ?

? ? ? private static final Singleton INSTANCE = new Singleton();? ?

? ? }? ?

? ? private Singleton (){}? ?

? ? public static final Singleton getInstance() {? ?

? ? ? return LazyHolder.INSTANCE;? ?

? ? }? ?

}

第三種比上面1.2都好一些,即實(shí)現(xiàn)了線程安全,又避免了同步帶來(lái)的性能影響

二.餓漢式單例

//餓漢式單例類.在類初始化時(shí),已經(jīng)自行實(shí)例化

public class Singleton1 {?

? ? private Singleton1() {}?

? ? private static final Singleton1 single = new Singleton1();?

? ? //靜態(tài)工廠方法?

? ? public static Singleton1 getInstance() {?

? ? ? ? return single;?

? ? }?

}

餓漢式再累創(chuàng)建的同事就已經(jīng)創(chuàng)建好一個(gè)靜態(tài)的對(duì)象供系統(tǒng)使用,以后不再改變,所以天生的是線程安全的.

三.登記式單例

//類似Spring里面的方法,將類名注冊(cè),下次從里面直接獲取。

public class Singleton3 {?

? ? private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();?

? ? static{?

? ? ? ? Singleton3 single = new Singleton3();?

? ? ? ? map.put(single.getClass().getName(), single);?

? ? }?

? ? //保護(hù)的默認(rèn)構(gòu)造子?

? ? protected Singleton3(){}?

? ? //靜態(tài)工廠方法,返還此類惟一的實(shí)例?

? ? public static Singleton3 getInstance(String name) {?

? ? ? ? if(name == null) {?

? ? ? ? ? ? name = Singleton3.class.getName();?

? ? ? ? ? ? System.out.println("name == null"+"--->name="+name);?

? ? ? ? }?

? ? ? ? if(map.get(name) == null) {?

? ? ? ? ? ? try {?

? ? ? ? ? ? ? ? map.put(name, (Singleton3) Class.forName(name).newInstance());?

? ? ? ? ? ? } catch (InstantiationException e) {?

? ? ? ? ? ? ? ? e.printStackTrace();?

? ? ? ? ? ? } catch (IllegalAccessException e) {?

? ? ? ? ? ? ? ? e.printStackTrace();?

? ? ? ? ? ? } catch (ClassNotFoundException e) {?

? ? ? ? ? ? ? ? e.printStackTrace();?

? ? ? ? ? ? }?

? ? ? ? }?

? ? ? ? return map.get(name);?

? ? }?

? ? //一個(gè)示意性的商業(yè)方法?

? ? public String about() {? ? ?

? ? ? ? return "Hello, I am RegSingleton.";? ? ?

? ? }? ? ?

? ? public static void main(String[] args) {?

? ? ? ? Singleton3 single3 = Singleton3.getInstance(null);?

? ? ? ? System.out.println(single3.about());?

? ? }?

}

登記式單例實(shí)際上維護(hù)了一組單例類的實(shí)例,將這些實(shí)例存在一個(gè)Map(登記簿)中,對(duì)于已經(jīng)登記過(guò)的實(shí)例,

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

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

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