概述
在面對象中我們經常會遇到這樣的一種情況,一個類能且只能執行個體化一個對象,前人們就想著各種各樣的方法去解決這個問題,經過無數次的嘗試和創新終於出現了一個好的方法,於是,單例模式就產生了。
單例模式 概念
保證一個類僅有一個執行個體,並且提供一個訪問它的全域訪問點。
描述
我們在編寫程式的時候,要使一個類只能執行個體化一個對象的時候,我們有多種方法:
1、在用戶端類中直接寫下代碼。這種方式連面向過程的要求都沒有達到,如果這樣的化,如果多個地方需要運用該對象,那豈不要每個地方都要寫下這些代碼,這樣一旦需要修改改代碼時,就非常的麻煩,所以,一般不用。
2、在用戶端類中建立一個方法,這個方法通過一些邏輯等運算使該類的對象唯一了。這個方法充分的體現出面向過程的思想,具體面向過程和物件導向之間的關係這裡就不再多說了。一般也不用這種方法。
3、這個方法就是把之前說的那個方法(確定對象唯一性),寫在該類裡面,這個時候就要注意:建構函式必須為自己寫的私人方法,如果不是私人的建構函式,這個類就可以被任意的執行個體化了;該類類型的物件變數一定要是全域變數(可以是靜態,也可以是非靜態;可以是第一次用的時候建立,也可以在第一次用之前建立),如果是局部變數的話,那麼會執行個體化無數多個執行個體;方法一定要為靜態類型的,因為靜態方法相當於類,類可以不用執行個體化成對象而調用靜態方法。
其實第三中方法就是單例模式的應用,單例模式的UML圖如
應用
上述的描述一般是在單線程中的應用,但是,如果要是在多線程中如何運用單例模型呢?那就是對單例類的對象加鎖。無論是多線程還是單線程,單例類只建立一個對象,這個是一定的,但是,如果是多線程的話,對象可能會出現一會被這個線程使用,一會兒被那個線程使用,造成程式結果出錯,為了避免這種情況的發生出現了加鎖的概念,就是一個線程使用這個對象的時候,必須對其加鎖,這樣別的線程就不會打擾你使用的這個線程。在加鎖的時候要注意,一般會藉助一個輔助對象,如果我們直接針對單例對象,那麼,如果單例對象還沒有建立的話就會出現錯誤。
注意
如果單例物件變數是在聲明的時候就對其進行建立的靜態變數,這種類的類型就叫做餓漢式單例類;其他情況只能在第一次被使用的時候執行個體化該對象,這中類的類型就叫做懶漢式單例類。
靜態變數可以理解為類,當類調入記憶體中的時候,那麼靜態變數(必須是聲明並建立的形式)相應的也就有了。
總結
單例模式:單(類)—單(對象),保證一個實體類有且只有一個對象。
原型模式:單(類)—單(對象)—多(對象),對象的複製。
簡單原廠模式:便於擴充新的類。
Factory 方法模式:便於已編寫的具體類的轉換。
抽象原廠模式:減少代碼的重複性。