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

單例模式(Singleton):在應(yīng)用這個(gè)模式時(shí),單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一個(gè)的全局對(duì)象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為。比如在某個(gè)服務(wù)器程序中,該服務(wù)器的配置信息存放在一個(gè)文件中,這些配置數(shù)據(jù)由一個(gè)單例對(duì)象統(tǒng)一讀取,然后服務(wù)進(jìn)程中的其他對(duì)象再通過這個(gè)單例對(duì)象獲取這些配置信息。**這種方式簡化了在復(fù)雜環(huán)境下的配置管理。 **

**實(shí)現(xiàn)單例模式的思路是: **
   一個(gè)類能返回對(duì)象一個(gè)引用(永遠(yuǎn)是同一個(gè))和一個(gè)獲得該實(shí)例的方法(必須是靜態(tài)方法,通常使用getInstance這個(gè)名稱);當(dāng)我們調(diào)用這個(gè)方法時(shí),如果類持有的引用不為空就返回這個(gè)引用,如果類保持的引用為空就創(chuàng)建該類的實(shí)例并將實(shí)例的引用賦予該類保持的引用;同時(shí)我們 還將該類的構(gòu)造函數(shù)定義為私有方法,這樣其他處的代碼就無法通過調(diào)用該類的構(gòu)造函數(shù)來實(shí)例化該類的對(duì)象,只有通過該類提供的靜態(tài)方法來得到該類的唯一實(shí)例。

需要注意的地方: **
  
單例模式在多線程的應(yīng)用場合下必須小心使用**。如果當(dāng)唯一實(shí)例尚未創(chuàng)建時(shí),有兩個(gè)線程同時(shí)調(diào)用創(chuàng)建方法,那么它們同時(shí)沒有檢測(cè)到唯一實(shí)例的存在,從而同時(shí)各自創(chuàng)建了一個(gè)實(shí)例, 這樣就有兩個(gè)實(shí)例被構(gòu)造出來,從而違反了單例模式中實(shí)例唯一的原則。 解決這個(gè)問題的辦法是為指示類是否已經(jīng)實(shí)例化的變量提供一個(gè)互斥鎖(雖然這樣會(huì)降低效率)。

**優(yōu)點(diǎn): **
1.在單例模式中,活動(dòng)的單例只有一個(gè)實(shí)例,對(duì)單例類的所有實(shí)例化得到的都是相同的一個(gè)實(shí)例。這樣就防止其它對(duì)象對(duì)自己的實(shí)例化,確保所有的對(duì)象都訪問一個(gè)實(shí)例
2.單例模式具有一定的伸縮性,類自己來控制實(shí)例化進(jìn)程,類就在改變實(shí)例化進(jìn)程上有相應(yīng)的伸縮性。
3.提供了對(duì)唯一實(shí)例的受控訪問。
4.由于在系統(tǒng)內(nèi)存中只存在一個(gè)對(duì)象,因此可以 節(jié)約系統(tǒng)資源,當(dāng) 需要頻繁創(chuàng)建和銷毀的對(duì)象時(shí)單例模式無疑可以提高系統(tǒng)的性能。
5.允許可變數(shù)目的實(shí)例。
6.避免對(duì)共享資源的多重占用。
**缺點(diǎn): **
1.不適用于變化的對(duì)象,如果同一類型的對(duì)象總是要在不同的用例場景發(fā)生變化,單例就會(huì)引起數(shù)據(jù)的錯(cuò)誤,不能保存彼此的狀態(tài)。
2.由于單利模式中沒有抽象層,因此單例類的擴(kuò)展有很大的困難。
3.單例類的職責(zé)過重,在一定程度上違背了“單一職責(zé)原則”。
4.濫用單例將帶來一些負(fù)面問題,如為了節(jié)省資源將數(shù)據(jù)庫連接池對(duì)象設(shè)計(jì)為的單例類,可能會(huì)導(dǎo)致共享連接池對(duì)象的程序過多而出現(xiàn)連接池溢出;如果實(shí)例化的對(duì)象長時(shí)間不被利用,系統(tǒng)會(huì)認(rèn)為是垃圾而被回收,這將導(dǎo)致對(duì)象狀態(tài)的丟失。
使用注意事項(xiàng):
1.使用時(shí)不能用反射模式創(chuàng)建單例,否則會(huì)實(shí)例化一個(gè)新的對(duì)象
2.使用懶單例模式時(shí)注意線程安全問題
3.餓單例模式和懶單例模式構(gòu)造方法都是私有的,因而是不能被繼承的,有些單例模式可以被繼承(如登記式模式)
適用場景:
單例模式只允許創(chuàng)建一個(gè)對(duì)象,因此節(jié)省內(nèi)存,加快對(duì)象訪問速度,因此對(duì)象需要被公用的場合適合使用,如多個(gè)模塊使用同一個(gè)數(shù)據(jù)源連接對(duì)象等等。如:
1.需要頻繁實(shí)例化然后銷毀的對(duì)象。
2.創(chuàng)建對(duì)象時(shí)耗時(shí)過多或者耗資源過多,但又經(jīng)常用到的對(duì)象。
3.有狀態(tài)的工具類對(duì)象。
4.頻繁訪問數(shù)據(jù)庫或文件的對(duì)象。
以下都是單例模式的經(jīng)典使用場景:
  1.資源共享的情況下,避免由于資源操作時(shí)導(dǎo)致的性能或損耗等。如上述中的日志文件,應(yīng)用配置。
  2.控制資源的情況下,方便資源之間的互相通信。如線程池等。
應(yīng)用場景舉例:
  1.外部資源:每臺(tái)計(jì)算機(jī)有若干個(gè)打印機(jī),但只能有一個(gè)PrinterSpooler,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)。內(nèi)部資源:大多數(shù)軟件都有一個(gè)(或多個(gè))屬性文件存放系統(tǒng)配置,這樣的系統(tǒng)應(yīng)該有一個(gè)對(duì)象管理這些屬性文件
  2. Windows的Task Manager(任務(wù)管理器)就是很典型的單例模式(這個(gè)很熟悉吧),想想看,是不是呢,你能打開兩個(gè)windows task manager嗎? 不信你自己試試看哦~
  3. windows的Recycle Bin(回收站)也是典型的單例應(yīng)用。在整個(gè)系統(tǒng)運(yùn)行過程中,回收站一直維護(hù)著僅有的一個(gè)實(shí)例。
  4. 網(wǎng)站的計(jì)數(shù)器,一般也是采用單例模式實(shí)現(xiàn),否則難以同步。
   5. 應(yīng)用程序的日志應(yīng)用,一般都何用單例模式實(shí)現(xiàn),這一般是由于共享的日志文件一直處于打開狀態(tài),因?yàn)橹荒苡幸粋€(gè)實(shí)例去操作,否則內(nèi)容不好追加。
  6. Web應(yīng)用的配置對(duì)象的讀取,一般也應(yīng)用單例模式,這個(gè)是由于配置文件是共享的資源。
  7. 數(shù)據(jù)庫連接池的設(shè)計(jì)一般也是采用單例模式,因?yàn)閿?shù)據(jù)庫連接是一種數(shù)據(jù)庫資源。數(shù)據(jù)庫軟件系統(tǒng)中使用數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關(guān)閉數(shù)據(jù)庫連接所引起的效率損耗,這種效率上的損耗還是非常昂貴的,因?yàn)楹斡脝卫J絹砭S護(hù),就可以大大降低這種損耗。
  8. 多線程的線程池的設(shè)計(jì)一般也是采用單例模式,這是由于線程池要方便對(duì)池中的線程進(jìn)行控制。
   9. 操作系統(tǒng)的文件系統(tǒng),也是大的單例模式實(shí)現(xiàn)的具體例子,一個(gè)操作系統(tǒng)只能有一個(gè)文件系統(tǒng)。
  
實(shí)現(xiàn)單利模式的原則和過程:
1.單例模式:確保一個(gè)類只有一個(gè)實(shí)例,自行實(shí)例化并向系統(tǒng)提供這個(gè)實(shí)例
2.單例模式分類:餓單例模式(類加載時(shí)實(shí)例化一個(gè)對(duì)象給自己的引用),懶單例模式(調(diào)用取得實(shí)例的方法如getInstance時(shí)才會(huì)實(shí)例化對(duì)象)(java中餓單例模式性能優(yōu)于懶單例模式,c++中一般使用懶單例模式)
3.單例模式要素:
a.私有構(gòu)造方法
b.私有靜態(tài)引用指向自己實(shí)例
c.以自己實(shí)例為返回值的公有靜態(tài)方法

Double Check Lock:

class Singleton{
        private Singleton() {
        }
        public static Singleton instance = null;

        public static Singleton getInstance() {
                if (instance == null) {
                        synchronized (Singleton.class) {
                                if (instance == null) {
                                        instance = new Test();
                                }
                        }
                }
                return instance;
        }
}

優(yōu)點(diǎn)
資源利用率高,第一次執(zhí)行g(shù)etInstance()時(shí)單例對(duì)象才會(huì)被實(shí)例化,效率高。
缺點(diǎn)
第一次加載時(shí)反應(yīng)稍慢,由于java內(nèi)存模型一些原因偶爾失敗 。在高并發(fā)環(huán)境下也有一定的缺陷,雖然發(fā)生概率很小。

DCL模式是使用最多的單例實(shí)現(xiàn)方式,它能夠在需要時(shí)才實(shí)例化單例對(duì)象,并且在絕大多數(shù)場景下保證單例對(duì)象的唯一性。除非代碼在并發(fā)場景復(fù)雜或者低于 JDK6版本下使用,否則,這種方式一般能夠滿足需求。

靜態(tài)內(nèi)部類單例模式:

class Singleton{
        private Singleton() {
        }
        private static class SingletonHelp {
               private static final Singleton instance = new Singleton();
        }

        public static Singleton getInstance() {
                return SingletonHelp.instance;
        }

當(dāng)?shù)谝淮渭虞dSingleton類時(shí)并不會(huì)初始化Instance,只有在第一次調(diào)用getInstance時(shí)才會(huì)導(dǎo)致實(shí)例初始化。因此,第一次調(diào)用getInstance方法會(huì)導(dǎo)致虛擬機(jī)加載SingletonHelp類,這種方式不僅確保線程安全,也能夠保證單例對(duì)象的唯一性,同時(shí)也延遲了單例的實(shí)例化,所以這是推薦使用的單例模式實(shí)現(xiàn)方式。


轉(zhuǎn)自:單利模式的優(yōu)缺點(diǎn)和使用場景
參考:《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 目錄 本文的結(jié)構(gòu)如下: 什么是單例模式 為什么要用該模式 模式的結(jié)構(gòu) 代碼示例 優(yōu)點(diǎn)和缺點(diǎn) 適用環(huán)境 模式應(yīng)用 總...
    w1992wishes閱讀 482評(píng)論 1 2
  • 單例模式 介紹 為了節(jié)約系統(tǒng)資源,有時(shí)需要確保系統(tǒng)中某個(gè)類只有唯一一個(gè)實(shí)例,當(dāng)這個(gè)唯一實(shí)例創(chuàng)建成功之后,我們無法再...
    666真666閱讀 414評(píng)論 0 6
  • 單例模式(Singleton Pattern)是眾多設(shè)計(jì)模式中較為簡單的一個(gè),同時(shí)它也是面試時(shí)經(jīng)常被提及的問題,如...
    廖少少閱讀 649評(píng)論 0 1
  • 1. 單例模式 確保某一個(gè)對(duì)象只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)程序提供這個(gè)實(shí)例。 優(yōu)點(diǎn) 由于單例模式在內(nèi)存中只...
    Mr希靈閱讀 6,529評(píng)論 0 5
  • 寫在前面# 其實(shí)我也不知道想說什么,來簡書已經(jīng)足足15天了,每天都在通過文字總結(jié)和分享自己的所學(xué)知識(shí),寫技術(shù)文章好...
    孑然自安閱讀 2,099評(píng)論 1 9

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