概念
單例模式是結(jié)構(gòu)最簡(jiǎn)單的設(shè)計(jì)模式,通過單例模式可以保證在整個(gè)系統(tǒng)中的一個(gè)類只有一個(gè)實(shí)例,從而節(jié)約系統(tǒng)資源。舉個(gè)例子,比如windows電腦下的任務(wù)管理器只能打開一個(gè),這個(gè)就是單例模式,如果不這樣做,則會(huì)彈出多個(gè)窗口,但這些窗口顯示的內(nèi)容完全一樣,浪費(fèi)了資源。
單例模式定義:確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)來訪問這個(gè)唯一實(shí)例。
單例模式有3個(gè)要點(diǎn):
1、某個(gè)類只能有一個(gè)實(shí)例。
2、該類必須自行創(chuàng)建這個(gè)實(shí)例。
3、該類必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。
結(jié)構(gòu)與實(shí)現(xiàn)
單例模式只有一個(gè)類,類圖如下:
單例類擁有一個(gè)私有的構(gòu)造方法,保證外部無法通過new關(guān)鍵字來進(jìn)行實(shí)例化,此外,它還包含一個(gè)靜態(tài)私有成員變量和靜態(tài)公有的工廠方法,該工廠負(fù)責(zé)檢驗(yàn)實(shí)例的存在性并實(shí)例化自己,然后存儲(chǔ)在成員變量中。
按照被實(shí)例化的時(shí)機(jī),單例模式可以分為兩大類,懶漢模式和餓漢模式。
1、餓漢式
當(dāng)類加載的時(shí)候就進(jìn)行實(shí)例化,這種方式叫做餓漢式。
public class EagerSingleton {
//static 變量在類加載的時(shí)候就已經(jīng)初始化。
private static EagerSingleton instance = new EagerSingleton();
//private 構(gòu)造,保證外部無法訪問
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return instance;
}
}
2、懶漢式
故名思義,比較懶,用的時(shí)候在實(shí)例化,也叫做延遲加載。直接上doubleCheck。
public class LazySingleton {
private static volatile LazySingleton instance = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
//判斷是否實(shí)例化過,是的話,則直接返回。 步驟一
if (instance == null) {
//防止多線程同時(shí)訪問,造成多次實(shí)例化。
synchronized (LazySingleton.class) {
//兩個(gè)線程情況下,A線程走到這里,B線程還在synchronized 外等待,
// 當(dāng)B線程進(jìn)入synchronized后,A線程已經(jīng)實(shí)例化完成,所以需要再次判斷,防止多次實(shí)例化。
if (instance == null) {
// 步驟二
instance = new LazySingleton();
}
}
}
return instance;
}
}
這里之所以使用volatile來修飾,是為了保證原子性和有序性。
實(shí)例化一個(gè)對(duì)象主要分為三部分
1、先給對(duì)象分配一個(gè)內(nèi)存空間。
2、創(chuàng)建該對(duì)象的引用
3、將該引用指向該存儲(chǔ)空間。
當(dāng)線程A走到上面代碼的步驟二時(shí),僅僅是完成了上面實(shí)例化對(duì)象三步中的第一步,但線程B這時(shí)候走到了上面代碼的步驟一,判斷不為null,則直接返回,此時(shí)對(duì)象還未實(shí)例化完成,這就發(fā)生了錯(cuò)誤,所以需要使用volatile來進(jìn)行修飾。
3、使用靜態(tài)內(nèi)部類
使用靜態(tài)內(nèi)部類也是懶漢式的方式之一,代碼如下
public class InnerClassSingleton {
private static class InnerClass {
private static InnerClassSingleton instance = new InnerClassSingleton();
}
private InnerClassSingleton() {
}
public static InnerClassSingleton getInstance() {
return InnerClass.instance;
}
}
只有當(dāng)?shù)谝淮握{(diào)用內(nèi)部類的時(shí)候,才會(huì)實(shí)例化該變量,從而保證了單例性。文章來源:http://www.zghlxwxcb.cn/news/detail-495913.html
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1、單例模式自己對(duì)外提供了唯一的實(shí)例,可以控制客戶的使用。
2、節(jié)約系統(tǒng)資源。
缺點(diǎn):
1、因?yàn)闆]有抽象層,擴(kuò)展性較差。
2、違背單一職責(zé),該類既創(chuàng)建對(duì)象又有業(yè)務(wù)方法,將對(duì)象的創(chuàng)建和使用耦合在了一起。
3、狀態(tài)丟失。如果實(shí)例出來的對(duì)象長(zhǎng)期不使用,會(huì)被垃圾回收,下次會(huì)創(chuàng)建出和之前不同的對(duì)象。文章來源地址http://www.zghlxwxcb.cn/news/detail-495913.html
到了這里,關(guān)于設(shè)計(jì)模式篇---單例模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!