設計模式 單例模式

2021-10-18 15:08:49 字數 2684 閱讀 5351

單例模式:指乙個類只有乙個例項,且該類只能由自己自行建立這個例項的一種模式,對外提供乙個獲取例項的方法,不需要例項化該類的物件。

單例模式有三個特點:

單例類只有乙個物件

該單例物件必須由單例類自行建立

單例類對外提供乙個訪問該單例的全域性訪問點

優點

單例模式可以保證記憶體裡只有乙個例項,減少了記憶體的開銷

可以避免對資源的多重占用

單例模式設定全域性訪問點,可以優化和共享資源的訪問

缺點

不適用於經常變化的物件,入同一型別的物件經常在不同的場景下變化,容易引起資料錯誤

單例模式一般沒有抽象層,擴充套件困難,違背了開閉原則

單例模式所有的**都寫在了乙個類中,可能會違背單一職責原則

實現單例模式需要先將構造方法私有化,這裡為了減少**量,就省略了私有化構造方法的**

懶漢式,顧名思義,非常的懶,只有在用到這個物件的時候才會去初始化

優點:

節省記憶體,如果物件一直不被使用,則不會初始化

缺點:

執行緒不安全

public

class

singleton

return singleton;

}}

普通懶漢式是執行緒不安全,例如有多個執行緒同步獲取例項,那麼同時進行物件非空判斷,在同一時間都判斷物件為空,然後進行建立,則會建立出多個物件,這裡使用同步鎖來保證執行緒安全

優點

執行緒安全

缺點

效率十分低下,因為對於物件的非空判斷只需要在初始化時判斷就可以,但是同步的加入,使得每次獲取物件都要先拿到鎖再判斷非空,獲取鎖的過程是非常浪費資源的,所以使用同步鎖效率會很低。

public

class

singleton

return singleton;

}}

雙重鎖,就是將同步鎖,下移至物件為空時進行初始化,這樣,就是所有的執行緒同時判斷物件為空,初始化物件的執行緒也只有拿到鎖的哪乙個。

public

class

singleton}}

return singleton;

}}

但是這段**,在jdk1.5之前,是有乙個隱患的,標記為label哪一行,理想的執行過程應該是這樣的

分配記憶體空間

初始化物件

將物件指向剛才分配的記憶體空間

但是,有些編譯器為了效能問題,可能會將第二步與第三步進行重排序,順序就變成了

分配記憶體空間

將物件指向剛才分配的記憶體空間

初始化物件

這樣一來,如果多個執行緒(a、b、c)同時進來,a執行緒正在初始化物件,正好執行完了分配記憶體空間,此時物件已經不為空了,然後b、c執行緒進來獲取物件,判斷物件不為空,獲取物件,但是物件並未初始化完成,那麼這個時候獲取到的就是乙個錯誤的物件。

解決方案

使用volatile修飾符修飾物件,讓編譯器不對這個物件進行重排序。使用了volatile關鍵字後,重排序被禁止,所有的寫(write)操作都將發生在讀(read)操作之前。

public

class

singleton}}

return singleton;

}}

這個問題在jdk1.5之後已經被sun公司解決了,所以jdk1.5之後不需要volatile修飾符。

餓漢式,顧名思義,就是很飢餓的意思,不管這個例項能不能用得上,我都在程式啟動時,就初始化物件

優點

不會出現執行緒不安全的問題,初始化在獲取物件之前就已經完成了,所有的執行緒拿到的都是同乙個物件

缺點

因為物件不一定能用上,容易造成記憶體空間的浪費

public

class

singleton

}

靜態內部類就很好的解決了執行緒不安全和記憶體空間浪費的問題,這個方案是將物件儲存在內部的乙個靜態類中,只有在需要用到這個物件時,才會進行初始化(靜態內部類在程式啟動時不會進行載入,只有在使用到外部類時才會被載入,具體細節請參考jvm虛擬機器相關資料)

public

class

singleton

private

static

class

singletoninstance

}

以上五種實現單例模式的方式,都存在反射攻擊和序列化以及反序列化之後出現多個例項的問題,但是列舉不會,因為列舉不能被例項化,自始至終都是只有乙個型別,不管是序列化和反序列化,還是通過反射構建例項,都不會得到兩個物件。

public

enum singleton

}

呼叫方式:

public

class

main

}

設計模式 單例模式

單例模式 singleton pattern 是乙個比較簡單的模式,其定義如下 ensure a class has only one instance,and provide a golbal point of acess to it.確保某乙個類只有乙個例項,而且自行例項化並且向整個系統提供這個...

設計模式 單例模式

class testsingleton static public function instance return self testsingleton private function clone public function setsinvar sinvar public function ...

設計模式 單例模式

單例模式的目的是保證類在系統中只被例項化一次,由該唯一的例項來為系統提供服務.單例模式主要用於保證服務的統一,比如獲取統一的編號服務,模仿oracle的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...