設計模式(一)單例模式

2021-10-09 08:49:45 字數 2808 閱讀 2736

建立型模式,單例類有且僅有乙個物件。並且對唯一物件提供全域性訪問點,不需要例項化該類的物件就可以實現。

單例類只能有乙個例項。

單例類必須自己建立自己的唯一例項。

單例類必須給所有其他物件提供這一例項。

需要生成唯一序列的環境(計數器、開啟**站的視窗、多執行緒的執行緒池等)。

需要頻繁例項化然後銷毀的物件。

建立物件耗時/耗資源過多,但是經常用到的物件。

方便資源互相通訊的環境。

兩個步驟:

將類的構造方法定義為私有方法,其他類只能通過該類提供的靜態方法來得到該類的唯一例項。

在該類內提供乙個靜態方法,當我們呼叫這個方法時,如果類保持的引用不為空就返回這個引用,如果類保持的引用為空就建立該類的例項並將例項的引用賦予該類保持的引用。

餓漢式與懶漢式

餓漢式是在類建立時就進行例項化,餓漢式是指在需要的時候再建立類的例項化。

懶漢式,執行緒不安全

public

class

singleton

public

static singleton getinstance()

return instance;

}}

不支援多執行緒,沒有加鎖synchronized,嚴格意義上來說不算單例模式。

懶漢式,執行緒安全

public

class

singleton

public

static

synchronized singleton getinstance()

return instance;

}}

支援多執行緒,但加鎖會影響效率。(getinstance()的效能對應用程式不是很關鍵,因為使用不頻繁)

餓漢式

public

class

singleton

public

static singleton getinstance()

}

基於classloader機制避免了多執行緒的同步問題,但類在載入時就初始化,浪費記憶體。

classloader機制

classloader是用來載入class的,負責將class的位元組碼轉換成記憶體形式的class物件。位元組碼可以來自磁碟檔案* .class,也可以是jar包裡的* .class,也可以來自遠端伺服器提供的位元組流。jvm執行並不是一次性載入所需要的全部類的,程式在執行時會逐漸遇到許多不認識的新類,此時就會呼叫classloader來載入這些類,載入完成後就會將class物件存在classloader裡面。

jvm在載入類的時候,都是通過classloader的loadclass()方法來載入class的,loadclass使用雙親委派模式。

load:使用指定的二進位制名稱來載入類,這個方法的預設實現按照以下順序查詢類: 呼叫findloadedclass(string)方法檢查這個類是否被載入過 使用父載入器呼叫loadclass(string)方法,如果父載入器為null,類載入器裝載虛擬機器內建的載入器呼叫findclass(string)方法裝載類, 如果,按照以上的步驟成功的找到對應的類,並且該方法接收的resolve引數的值為true,那麼就呼叫resolveclass(class)方法來處理類。 classloader的子類最好覆蓋findclass(string)而不是loadclass()方法。 除非被重寫,這個方法預設在整個裝載過程中都是同步的(執行緒安全的)。

雙重校驗鎖(dcl)

public

class

singleton

public

static singleton getinstance()

}}return singleton;

}}

這種方式採用雙鎖機制,安全且在多執行緒情況下能保持高效能。getinstance() 的效能對應用程式很關鍵。

靜態內部類

public

class

singleton

private singleton (

)public

static

final singleton getinstance()

}

和雙重校驗鎖功效一樣,但是實現更加簡單。對靜態域使用延遲初始化,應使用這種方式而不是雙檢鎖方式。這種方式只適用於靜態域的情況,雙檢鎖方式可在例項域需要延遲初始化時使用。同時實現了lazy loading(只有顯式呼叫getinstance方法時才會被例項化)。

列舉

public

enum singleton

}

比較少用,但它是實現單例模式的最佳方法,自動支援序列化機制,防止反序列化,不能通過反射建立新的物件。也能避免多執行緒同步問題。

總結:一般情況下建議使用第3種餓漢方式,明確要實現lazy loading時用第5種靜態內部類方式,涉及到反序列化時用第6種列舉方式,有其他特殊需求可考慮使用第4種雙重校驗鎖機制。

jvm規範嚴格定義了何時需要對類進行初始化:

通過new關鍵字、反射、clone、反序列化機制例項化物件時。

呼叫類的靜態方法時。

使用類的靜態欄位或對其賦值時。

通過反射呼叫類的方法時。

初始化該類的子類時(初始化子類前其父類必須已經被初始化)。

jvm啟動時被標記為啟動類的類(簡單理解為具有main方法的類)。

設計模式 一 單例模式

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

設計模式(一) 單例模式

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

設計模式(一) 單例模式

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