05.15 Java編程細節——為什麼要用靜態工廠方法代替構造器

通常情況下我們會利用類的構造器對其進行實例化,這似乎毫無疑問。但“靜態工廠方法”也需要引起我們的高度注意。

什麼是“靜態工廠方法”?這不同於設計模式中的工廠方法,我們可以理解它為“在一個類中用一個靜態方法來返回這個類的實例”,例如:

Java編程細節——為什麼要用靜態工廠方法代替構造器

它是一個“方法”,那麼它不同於構造器,它可以隨意修改方法名,這就帶來第一個優點——有名稱。有時一個類的構造器往往不止一個,而它們的名稱都是相同的,不同的僅僅是參數,如果不同參數帶來不同的含義這樣對於調用方來說除了註釋很難理解它們有什麼不同的含義。例如BigInteger(int, int, Random)返回一個素數,但調用者很難理解API設計者所要想表達的意思,如果此時有BigInteger.probablePrime靜態工廠方法,則能一目瞭然的清楚API設計者所要想表達的含義。舉一個JDK的例子:Executors類,在這個類中有newFixedThread、newSingleThreadExecutor、newCachedThreadPool等靜態方法,因為它們有“名字”,所有就較為清晰的明白API的含義。

靜態工廠方法第二個優點在於不用重複創建一個對象,實際上也就是勤加載或者稱為餓漢式的單例模式。例如:

Java編程細節——為什麼要用靜態工廠方法代替構造器

靜態工廠方法的第三個優點,可以返回原返回類型的任何子類型的。這句話初看不好理解,舉個JDK中的例子:Collections類。 

List list = Collections.synchronizedList(new ArrayList()) 

這個例子就說明了可以返回原返回類型的任何子類型的對象。

關於靜態工廠方法的第四個優點,在創建參數化類型實例的時候,它們使代碼變得更加簡潔,書中舉了一個例子:

Java編程細節——為什麼要用靜態工廠方法代替構造器

給集合類提供靜態工廠方法後:

Java編程細節——為什麼要用靜態工廠方法代替構造器

Java編程細節——為什麼要用靜態工廠方法代替構造器

  但是實際上從JDK7(包括JDK7)之後的集合類可以用以下簡潔的代碼代替:

Map<string>> m = new HashMap<>();/<string>

靜態工廠方法也有兩個缺點

一是公有的靜態方法所返回的非公有類不能被實例化,也就是說Collections.synchronizedList返回的SynchronizedList不能被實例化;

二是查找API比較麻煩,它們不像普通的類有構造器在API中標識出來,而是和其他普通靜態方法一樣,鑑於此,我們需要儘量使用以下幾種慣用名稱:

valueOf

of  

getInstance

  newInstance

getType

newType

Java編程細節——為什麼要用靜態工廠方法代替構造器


分享到:


相關文章: