標籤:單例模式 建立型設計模式 java原始碼 gof設計模式 餓漢式和飽漢式
一、描述
單例模式就是確保一個類只有一個執行個體對象,並且在執行個體對象必須自動建立,對外不提供該對象的構造方法,並向整個系統提供該執行個體。使用單例模式相當於整個系統共用該類的執行個體對象,對於java中的並發訪問有重要意義。
單例模式又分為餓漢模式和飽漢模式兩種,餓漢模式就是在類載入的時候就建立和初始化該類的唯一的執行個體對象,而飽漢模式是系統需要用到這個類的執行個體的時候才建立該對象。
二、單例模式的優缺點
優點:在單列模式中,用戶端調用類的執行個體時,只能調用一個公用的介面,這就為整個系統提供了一個共用的對象。因為在系統記憶體中只存在一個對象,所以可以節約系統資源,相對於那些需要頻繁建立和銷毀的對象的類來說無疑提高了效率。而且由類自己來控制執行個體化過程,類就在改變執行個體化進程上有相應的伸縮性。
缺點:實現單例模式的類在執行個體化後不能被別的類繼承;而且一個類只有唯一的對象,那麼這個單例類的職責就會過重,在一定程度上違背了“單一職責原則”;類的執行個體在初始化後就不能再更改也不適合於類的執行個體經常變動的情境;如果在分布式系統中,當系統中的單例類被複製到不同的虛擬機器下,在每個虛擬機器中都會建立一個執行個體對象,要分清具體哪個虛擬機器下運行哪個單例對象比較困難;再者,由於單例模式中的執行個體是一個共用的概念,在並發訪問時需要附加代碼保證其訪問安全性。
三、原始碼
package tong.yue.day4_25;import java.io.IOException;/** * 單例模式是一種非常常見的設計模式,即一個類只能有一個對象(執行個體),一般通過將該類的構造器私人化,來阻止在該類外建立該類的對象,並提供給外界一個唯一的對象(這個對象在該類中建立)。 * java中的單例模式常見的有兩種實現方式,一種是惡漢方式,即將該類對象用static休息並且在類載入的時候進行初始化; * 另一種是飽漢方式,在程式中需要用到該對象的時候才初始化,一旦初始化一次就不會再重建該對象。 * jdk中的Runtime類其實也是一種單例模式,而且其採用的是餓漢的方式。 * @author Administrator * */public class Singleton {public static void main(String[] args) {//餓漢式擷取單例類的對象Singleton_eager singleton = Singleton_eager.getInstance();singleton.print();//餓漢式擷取單例類的對象Singleton_lazy singleton_lazy = Singleton_lazy.getInstance();singleton_lazy.print();}}//餓漢式單例模式,在類載入的時候建立一個對象,之後就不再重複建立class Singleton_eager {//聲明為static類型,在類載入的時候建立一個對象private static Singleton_eager singleton_eager = new Singleton_eager();private Singleton_eager(){}public static Singleton_eager getInstance() {return singleton_eager;}public void print() {System.out.println(singleton_eager);}}//飽漢式單例模式,當程式第一次使用該類的對象時建立對象,只建立一次,之後就不再重複建立class Singleton_lazy{private static Singleton_lazy singleton_lazy = null;private Singleton_lazy(){}//單例對象的建立方法需要加上同步,因為在多線程並發訪問時要保證其訪問安全性和統一性。public synchronized static Singleton_lazy getInstance() {//若是第一次使用該對象,那個就建立一個,否則就使用一個已經建立好的對象if (singleton_lazy==null) {singleton_lazy = new Singleton_lazy();}return singleton_lazy;}public void print() {System.out.println(singleton_lazy);}}運行結果:
四、總結
以上兩種方案的建構函式和公用方法都是靜態(static),則這個類執行個體是共用的。只是餓漢式在類載入的時候已經建立了對象,每次調用的時候不用再建立而是直接返回已經建立好的執行個體。這樣節省了時間,但卻佔用了空間,執行個體本身為static的會一直駐留記憶體。
懶漢式在類載入時不建立對象,而是在程式使用到這個類的對象時才建立一次,以後每次使用該執行個體對象,則是判斷是否存在,若存在就載入,不存在就建立,這勢必會影響程式運行的速度。最關鍵的是,在並發的情況下,懶漢式是不安全的,如果兩個線程:線程1和線程2,在同一時間調用getInstance()方法,如果線程1先進入if語句剛剛判斷沒有該對象,準備建立對象時,線程發生了切換,然後線程2進行控制判斷if語句沒有對象也會建立,那麼就會有兩個執行個體被建立,所以懶漢式單例模式的getInstance()方法要加上同步控制符synchronized,以保證並發訪問的安全性。
java語言實現建立型設計模式—單例模式