java設計模式之單例設計模式,這樣設計才最好!
單例模式,顧名思義只有一個例項,該中設計模式主要應用的場景如下:
1.需要頻繁例項化然後銷燬的物件。
2.建立物件時耗時過多或者耗資源過多,但又經常用到的物件。
3.完全限制需要單一物件的,例如計數器等等。
單例模式
一、用類圖表示單例模式如下:
二、常見的幾種單例模式寫法,具體程式碼如下:
1、餓漢式-靜態常量
這種方法使用靜態常量的方式建立單例,靜態常量只在類被載入時執行一次,故Singleton1只會產生一個例項。那麼它在建立過程中是如何保證多執行緒安全的呢,類載入工程中,類初始化這一步驟中,jvm會執行
方法,該方法是由編譯器自動手機類中的所有類變數複製動作和靜態語句塊中的語句合併產生的,jvm會保證一個類的
方法在多執行緒操作時被正確的同步加鎖,保證同一時刻只有一個執行緒在操作,因此我們可以理解成,是jvm幫我們保證了多執行緒的安全性。
缺點:類載入時就例項化了,沒有實現“懶載入的過程”,假設類的建立過程很複雜,很消耗資源,在沒用到例項時就會被載入消耗資源,而且我們也很難保證該類不會在其他情況下被載入,那麼這一方法就不太適用了。
2、餓漢式-靜態程式碼塊
這種方法不在贅述,原理與上面靜態常量的方法類似。
3、懶漢式-同步方法
這種方法實現了“懶載入”過程。
優點:未使用該例項時並不建立,能很好的節省資源;
缺點:採用同步方法,極大的消耗系統性能,其實同步方法裡的判斷,大多數情況下是不會執行的;
4、懶漢式-同步程式碼塊
這種方法為了解決第三種方法消耗系統性能的問題,當判斷例項不存在時,才用同步程式碼塊來建立單個例項。
優點:大多數情況不會執行到同步程式碼塊,所以能提高效能;
缺點:並不能完全保證真正意義上的單例。為什麼這麼說呢,假設有兩個執行緒同時執行到了if(singleton == null)這一步,發現都沒有例項,這時第一執行緒拿到鎖,建立第一個例項,釋放鎖後第二執行緒拿到鎖,會接著建立第二個例項,這樣就違背了單例模式的根本原則。
5、懶漢式-同步程式碼塊-雙重檢查(推薦使用)
這種方法解決了第四種方法的單一性問題,線上程拿到鎖後,再次判斷例項是否存在,如果不存在則直接建立,如果建立了則直接跳過,返回已建立例項。這種雙重檢查應用很廣,在很多原始碼中都會使用到,大家有興趣可以扒扒jdk多執行緒原始碼。
優點:執行緒安全,效率高;
6、利用靜態內部類(推薦使用)
這種方法通餓漢式的實現方式相類似,都是通過類載入機制類保證執行緒的安全性和單一性,不同的是餓漢式在類載入時就被例項化了,沒有實現懶載入的過程,而這種方法在類載入時並沒有例項化,因為內部類並沒有被主動引用(有且僅有五種主動引用發生時才會對類初始化操作),所以並沒有被例項化,而只有當顯式地呼叫getInstance方法時,才主動引用了內部類,這時才會例項化,達到了懶載入的目的。
優點:執行緒安全,效率高;
7、利用列舉實現單例(推薦使用)
需要單例的類
這種方法採用了內部列舉類的方式來實現單例模式,當然也可以不用內部列舉類,直接使用列舉類也可以實現,方法殊途同歸。
首先在列舉中我們明確了構造方法是私有的,在訪問列舉例項時,會呼叫起構造方法,同時每個列舉例項都是static final的,保證了只能被例項化一次。所以列舉能很好的保證了單一性。單元素的列舉型別已經成為實現Singleton的最佳方法。
該方法不僅能避免多執行緒同步問題,而且還能防止反序列化重新建立新的物件。可能是因為列舉在JDK1.5中才新增,所以在實際專案開發中,很少見人這麼寫過。
好了,本篇文章就分享到這裡了。有興趣的新手夥伴們可以關注收藏起來,以後需要的時候可以多看看。如果有正在學java的程式設計師,可來我們的java技術學習扣qun哦:59789,1510裡面免費送java的視訊系統教程!