設計模式-單例模式

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

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

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

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

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

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

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

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

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


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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

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