重構:用靜態工廠方法代替構造方法
阿新 • • 發佈:2021-01-01
技術標籤:程式碼重構
對於類而言,為了讓客戶端獲取它自身的一個例項,最傳統的方法就是提供構造方法。除此之外,我們今天將介紹的靜態工廠方法也是被用得很廣泛的一種方式。比如Boolean
原始碼中將boolean
基本型別值轉換成一個Boolean
物件引用:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
如果不通過公有的構造方法,或者說除了公有的構造方法之外,類還可以給它的客戶端提供靜態工廠方法。提供靜態工廠方法而不是公有的構造方法,這樣做既有優勢,也有劣勢。
1. 優勢
(1)第一大優勢在於,靜態工廠方法是有名稱的。如果構造方法的引數本身沒有確切地描述正在建立的物件,那麼具有適當名稱的靜態工廠會更容易使用,產生的客戶端程式碼也更易於閱讀。
(2)第二大優勢在於,不必在每次呼叫它們的時候都建立一個新的物件。這使得不可變類可以使用預先建立好的物件,或者將構建好的例項快取起來,進行重複利用,從而避免建立不必要的重複物件。上訴Boolean.valueOf(boolean b)
方法就是如此,它從來不建立物件,而是返回快取中的物件。
(3)第三大優勢在於,它們可以返回原返回型別的任何子類物件。比如Arrays.asList()
方法返回的就是List
介面的一個子類物件。
2. 劣勢
(1)第一大劣勢在於,程式設計師很難發現它們。在API文件中,它們沒有像構造方法那樣在API文件中明確標識出來,因此,對於提供了靜態工廠方法而不是構造方法的類來說,要想查明如何例項化一個物件是非常困難的。這一點需要我們通過在類或者介面註釋中關注靜態工廠,並遵守標準的命名習慣來彌補這一劣勢。下面是靜態工廠方法的一些慣用名稱:
from
:型別轉換方法,它只有單個引數,返回該型別的一個物件。比如:Date date = Date.from(instant)
。of
:聚合方法,帶有多個引數,返回該型別的一個物件,把它們合併起來。比如:Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING)
。valueOf
:比如:BigDecimal.valueOf(long val)
。instance
或者getInstance
:大部分見於單例類。create
或者newInstance
:和instance
、getInstance
一樣,但create
或者newInstance
能夠確保每次呼叫都返回一個新的例項物件。get<Type>
:像getInstance
一樣,但是在工廠方法處於不同的類中的時候使用。比如:FileStore fs = Files.getFileStore(path)
。new<Type>
:像newInstance
一樣,但是在工廠方法處於不同的類中的時候使用。比如:BufferedReader br = Files.newBufferedReader(path)
。type
:get<Type>
和newType
的簡版,比如:List<Complaint> litany = Collections.list(legacyLitany)
。