? ? ? 從類獲取實例,最常用是利用構造器,其次就是利用靜態工廠方法。例如下面方法將boolean基本類型值轉化為Boolean對象引用:
public static Boolean valueOf(boolean b){
? ? ? ? ?return b ? Boolean.True : Boolean.False;
}
使用靜態工廠方法的優勢:
(1)它們有名稱,可以通過名稱確定應該調用哪個靜態工廠方法,而構造器名稱都一樣,僅憑借參數不同不容易確定應該調用哪個構造方法。
(2)不必再每次調用它們的時候都創建一個對象。
例如上面的valueOf方法,返回的Boolean.True如下所示是事先創建好的對象。所以如果程序經常請求創建相同的對象并且創建對象的代價很高,那么有助于性能提高。
public static final Boolean TRUE= new Boolean(true);
靜態工廠方法,為重復的調用返回相同對象,有助于類控制某個時刻哪些實例應該存在,這叫做實例受控類(instance controlled)
實例受控類->Singleton類,不可實例化類,不可變類不會存在兩個相等的實例,即a==b才有a.equals(b)
(3)它們可以返回原返回類型的任何子類型的對象。
這樣API可以返回對象,同時又不會使對象的類變成共有的。例如Java Collections Framework集合有32個便利實現,幾乎所有實現都通過靜態工廠方法在一個不可實例化的類中導出,所有返回對象的類都是非公有的。
public static> EnumSetnoneOf(Class elementType) {
Enum[] universe =getUniverse(elementType);
if(universe ==null)
throw new ClassCastException(elementType +" not an enum");
if(universe.length<=64)
return new RegularEnumSet<>(elementType,universe);
else
return new JumboEnumSet<>(elementType,universe);
}
RegularEnumSet和JumboEnumSet都是非公有類,返回類型根據元素的個數發生變化。但這個類型必須是聲明類型的子類型。這兩個實現類對客戶端不可見,客戶端也不需在意,以后刪除這種實現或增加新的子類實現不會造成不良影響。
靜態工廠方法返回的對象所屬的類,在編寫包含該靜態工廠方法的類時可以不必存在。這是服務提供者框架的基礎。
服務提供者框架:多個服務提供者實現一個服務,系統為服務提供者的客戶端提供多個實現,并把他們從多個實現中解耦出來。框架主要有以下四個組成部分:
服務接口:提供者實現 JDBC Connection
提供者注冊API:系統注冊,客戶端訪問 DriverManager.registerDriver
服務訪問API:客戶端獲取服務 DriverManager.getConnection
服務提供者接口:服務提供者接口 Driver
(4)創建參數化類型實例時,它們使代碼變得更加簡潔(這個現在沒那么重要了)
Map<String,List<String>> m=new HashMap<String,List<String>>();
用靜態工廠:
public static<K,V> HashMap<K,V> newInstance(){
? ? ? ? return new HashMap<K,V>();
}
現在提供自動識別功能,所以這種方法就沒必要了。
Map<String,List<String>>m=new HashMap>();
靜態工廠方法主要缺點
(1)類如果不含共有的或受保護的構造器,就不能被子類化。
這從某種程度上鼓勵使用復合而不是繼承。
(2)它們與其他的靜態方法實際沒有任何區別,不過隨著Javadoc工具的完善,丑小鴨會變成白天鵝的。或者用以下靜態方法名稱來標示:
valueOf(of):實際上是一種類型轉化方法
getInstance:返回的實例通過方法的參數來描述。
newInstance:保證每個返回的實例與其他的都不同。
getType
newType