設計模式(一)單例模式

2021-09-24 18:24:04 字數 3207 閱讀 9193

**單例模式:**無法使用new對乙個物件進行例項,只能呼叫內部的乙個方法,拿到乙個物件例項。

1、單例模式的好處:

單例模式適合於應用中頻繁建立的物件,如果是重量級的物件,更應該使用單例模式。比如配置檔案,如果不採用單例模式的話,每個配置檔案物件的內容都是一樣的,建立重複的物件就會浪費寶貴的記憶體,所以有必要使用單例模式,達到效能的提公升,減小了記憶體的開銷和gc的壓力。

2、單例模式實現的一般方式:

**2、單例模式實現的一般方式:

(1)餓漢模式(執行緒安全)

public class singleton1 

private static singleton1 single = new singleton();

// 靜態工廠方法

public static singleton1 getinstance()

}

直接在執行這個類的時候進行一次載入,之後直接訪問。顯然,這種方法沒有起到懶載入的效果,考慮到前面提到的和靜態類的對比,這種方法只比靜態類多了乙個記憶體常駐而已。

static對乙個類的載入由jvm例項,保證只實現乙個類,所以,是執行緒安全的

(2)懶漢模式(有兩種,分為執行緒安全和執行緒不安全的)

懶載入:按需載入,用的時候再建立

a.執行緒不安全的

class singletondemo2

public static singletondemo2 getinstance()

return single;

}}

缺點:沒有考慮到執行緒安全,可能存在多個訪問者同時訪問,並同時構造了多個物件的問題

在第一次兩個執行緒併發的時候,會出現同時構造多個物件,執行緒不安全

b.執行緒安全的(進行全域性加鎖)

public class single3 

public synchronized static single3 getinstance()

}

加鎖的三種方法總結:

加鎖加在類,鎖的是當前的類

加在普通方法,鎖的是當前這個new出來的類物件(同一時刻只能有乙個物件來訪問當前執行緒)

加在**塊,鎖的是當前**塊

缺點:用到鎖,涉及到底層作業系統的不斷互動來獲取鎖,獲取鎖首先要占有鎖,所以,效率不高

c.執行緒安全的(加了鎖,並且使用了雙重檢驗機制)加強版

class singleton4//懶漢式單例模式,要用兩次判空操作

// 私有構造

private singleton4() {}

private static singleton4 single = null;

// 雙重檢查

public static singleton4 getinstance() }}

return single;}}

常執行緒安全,但是,低概率的情況下也會執行緒不安全

一次只能是乙個執行緒操作,所以,進行了雙重判空,比b的全域性加鎖效率更高

保證了初始化的時候,兩個執行緒同時進來的時候,第二個不會再次建立single4

3、多執行緒實現單例模式的方式:

(1)static靜態**塊實現

class singleton5 

private static singleton5 single = null;

// 靜態**塊

static

public static singleton5 getinstance()

}

在類載入過程中實現,具體在使用階段獲取

(2)使用內部靜態類(推薦使用)

class singleton6 

// 靜態內部類

private static class innerobject

public static singleton6 getinstance()

}

使用內部類的好處是,靜態內部類不會在單例載入時就載入,而是在呼叫getinstance()方法時才進行載入,達到了類似懶漢模式的效果,而這種方法又是執行緒安全的。

(3)使用內部列舉類進行實現(推薦使用)

class singletonfactory 7

public singleton7 getinstance()

}public static singleton7 getinstance()

}

更簡潔,無償地提供了序列化機制,絕對防止對此例項化,即使是在面對複雜的序列化或者反射攻擊的時候。但是它仍然不是完美的——比如,在需要繼承的場景,它就不適用了

4、單例模式與靜態類的區分

「既然只使用乙個物件,為何不乾脆使用靜態類?」

(1)單例可以繼承和被繼承,方法可以被override,而靜態方法不可以。

(2)靜態方法中產生的物件會在執行後被釋放,進而被gc清理,不會一直存在於記憶體中。

(3)靜態類會在第一次執行時初始化,單例模式可以有其他的選擇,即可以延遲載入。

(4)基於2, 3條,由於單例物件往往存在於dao層(例如sessionfactory),如果反覆的初始化和釋放,則會占用很多資源,而使用單例模式將其常駐於記憶體可以更加節約資源。

(5)靜態方法有更高的訪問效率。

(6)單例模式很容易被測試。

5、幾個關於靜態類的誤解:

誤解一:靜態方法常駐記憶體而例項方法不是。

實際上,特殊編寫的例項方法可以常駐記憶體,而靜態方法需要不斷初始化和釋放。

誤解二:靜態方法在堆(heap)上,例項方法在棧(stack)上。

實際上,都是載入到特殊的不可寫的**記憶體區域中。

6、靜態類和單例模式情景的選擇:

情景一:不需要維持任何狀態,僅僅用於全域性訪問,此時更適合使用靜態類。

情景二:需要維持一些特定的狀態,此時更適合使用單例模式。

設計模式 一 單例模式

思路 1 如果其他程式能夠隨意用new建立該類物件,那麼就無法控制個數。因此,不讓其他程式用new建立該類的物件。2 既然不讓其他程式new該類物件,那麼該類在自己內部就要建立乙個物件,否則該類就永遠無法建立物件了。3 該類將建立的物件對外 整個系統 提供,讓其他程式獲取並使用。步驟 1 將該類中的...

設計模式(一) 單例模式

這種模式只涉及到乙個單一的類,該類負責建立自己的物件,並確保只建立乙個物件。單例只有乙個例項 單例類必須建立自己唯一的例項 單例類必須給其他物件提供這唯一的例項 由於當今的程式設計模型都是基於多執行緒方式,因此此處只介紹執行緒安全的幾種實現。第一次被呼叫時才建立物件,屬於懶載入 lazy init ...

設計模式(一) 單例模式

單例模式 保證執行記憶體中只有乙個實體的實現模式就是單例模式,最常見的有餓漢模式 懶漢模式兩種。餓漢模式 package com.madg.design.singleton public class hungry public hungry getinstance 懶漢模式 package com....