設計模式之單例模式

Singleton單類模式是最簡單的設計模式,它的主要作用是保證在程序運行生命週期中,使用了單類模式的類只能有一個實例對象存在。

單類模式有兩種實現方式:飽漢模式和餓漢模式,如下:

飽漢單例模式

public class Singleton1{
        //飽漢模式,聲明時就創建實例對象
	public static final Singleton1 instance = new Singleton1();
	//單類模式的構造方法必須爲private,以避免通過構造方法創建對象實例,
        //並且必須顯示聲明構造方法,以防止使用默認構造方法
	private Singleton1(){}
        //單類模式必須對外提供獲取實例對象的方法
        public static Singleton1 geInstance(){
	       return instance;
        }
}


餓漢單例模式

public class Singleton2{
        //餓漢模式,聲明時不創建實例對象
	public static Singleton2 instance;
	//單類模式的構造方法必須爲private,以避免通過構造方法創建對象實例,
        //並且必須顯示聲明構造方法,以防止使用默認構造方法
	private Singleton2(){}
        //單類模式必須對外提供獲取實例對象的方法,延遲初始化的單類模式必須使用synchronized同步關鍵字,否則多線程情況下很容易產生多個實例對象
        public static synchronized Singleton2 geInstance(){
	       //延遲初始化,只有當第一次使用時才創建對象實例
	       if(instance == null){
	           return new Singleton2();
                }
               return instance;
        }
}


 

一般認爲飽漢模式要比餓漢模式更加安全。

上面兩種Singleton單類設計模式的實現方式都隱藏有如下的問題:

(1).雖然構造方式的訪問修飾符爲private,即除了自身以外其他任何類都無法調用,但是通過反射機制的setAccessiable(true)方法可以訪問私有方法和屬性。因此Singleton單類模式必須考慮這種例外情況。

(2).對象序列化之後再反序列化時會生成新的對象,因此當Singleton單類模式類實現序列化接口時,必須顯式聲明所有的字段爲tranisent,並且提供如下的readResolve方法來防止通過序列化破壞單態模式:

3.使用Lazy initialization holder class模式實現單態:

 public class Singleton3 {  
    /** 
     * 類級的內部類,也就是靜態的成員式內部類,該內部類的實例與外部類的實例 
     * 沒有綁定關係,而且只有被調用到纔會裝載,從而實現了延遲加載 
     */  
    private static class SingletonHolder{  
        /** 
         * 靜態初始化器,由JVM來保證線程安全 
         */  
        private static Singleton3 instance = new Singleton3();  
    }  
    /** 
     * 私有化構造方法 
     */  
    private Singleton3(){  
    }  
    public static  Singleton3 getInstance(){  
        return SingletonHolder.instance;  
    }  
}


當getInstance方法第一次被調用的時候,它第一次讀取SingletonHolder.instance,導致SingletonHolder類得到初始化;而這個類在裝載並被初始化的時候,會初始化它的靜態域,從而創建Singleton的實例,由於是靜態的域,因此只會被虛擬機在裝載類的時候初始化一次,並由虛擬機來保證它的線程安全性。
這個模式的優勢在於,getInstance方法並沒有被同步,並且只是執行一個域的訪問,因此延遲初始化並沒有增加任何訪問成本。

public enum Singleton4{
	INSTANCE{
		public void doSomething(){
			……
		}
	};
	public abstract void doSomething();  
}


Singleton單類模式中只有一個INSTANCE枚舉元素,枚舉可以保證真個程序生命週期中只有一個實例對象存在,同時還避免了常規Singleton單類模式private構造方法被反射調用和序列化問題(枚舉提供了序列化保證機制,確保多次序列化和反序列化不會創建多個實例對象)。

注意:java中除了構造方法可以創建對象實例以外,還可以通過克隆方法(clone()是Object中的protected方法)來創建對象,若單類對象直接繼承自Object對象,則如果沒有提供具體clone方法實現,則當調用克隆方法創建對象時,會拋出運行時的異常CloneNotSupportedException。

若單類類繼承了實現克隆方法的類,則在單類類中必須覆蓋父類的克隆方法,顯式拋出異常CloneNotSupportedException。

另外,實現了單類模式的類不能再有派生子類,因爲構造方式是私有的,子類無法調用父類構造方法,因此達到了Final的效果。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章