首先忧勿,什么是靜態(tài)工廠方法梨撞。一般而言甩骏,如果一個(gè)類需要調(diào)用另一個(gè)類的變量和方法,那么該類需要先獲得另一個(gè)類的實(shí)例栗菜,最常用的的方法就是被調(diào)用類提供一個(gè)公有的構(gòu)造方法。但是蹄梢,還要另外一種方法疙筹,就是被調(diào)用類提供一個(gè)可以返回該類實(shí)例的靜態(tài)方法,該靜態(tài)方法稱為靜態(tài)工廠方法
。例如下面的例子(引自《Effective Java》)腌歉,將boolean基本類型值轉(zhuǎn)換成了一個(gè)Boolean對象引用:
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
優(yōu)點(diǎn)
1. 和構(gòu)造方法不一樣蛙酪,靜態(tài)工廠方法可以有自己明確的名字。比如newInstance
翘盖、getInstance
桂塞、valueOf
,可以更明確知道這些方法名字的意思馍驯。而構(gòu)造方法只能通過new類名來創(chuàng)建阁危,比如Person person = new Person()
。
2. 不必沒次調(diào)用時(shí)都創(chuàng)建一個(gè)新對象汰瘫。使用靜態(tài)工廠方法對外提供單例狂打,其實(shí)就是提前準(zhǔn)備好實(shí)例,這樣可以重復(fù)利用混弥,減少重復(fù)創(chuàng)建實(shí)例趴乡,不過這也需要注意線程安全問題。
3. 可以返回原返回類型的任何子類的對象蝗拿。這個(gè)可以這么理解晾捏,例如EnumSet
類,EnumSet
是抽象類是不能被實(shí)例化的哀托,但是可以通過里面的noneOf
靜態(tài)工廠方法返回它子類的對象惦辛,RegularEnumSet
和JumboEnumSet
都是EnumSet
的子類,代碼如下:
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
implements Cloneable, java.io.Serializable {
EnumSet(Class<E>elementType, Enum[] universe) {}
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
}
4.在創(chuàng)建參數(shù)化類型實(shí)例的時(shí)候仓手,它們使代碼變得更加簡潔胖齐。這條可以這么理解,比如在創(chuàng)建一個(gè)Map
類型對象時(shí)嗽冒,我們一般可以這么創(chuàng)建:
Map<String, List<String>> m = new HashMap<String, List<String>>();
但是在JDK7以上的版本呀伙,泛型參數(shù)是可以被推導(dǎo)出來的,所以可以有更簡潔的寫法:
Map<String, List<String>> m = new HashMap<>();
或者以后JDK可以提供這樣的寫法辛慰,但目前還不能:
Map<String, List<String>> m = HashMap.newInstance();
雖然標(biāo)準(zhǔn)的集合實(shí)現(xiàn)如HashMap并沒有工廠方法区匠,但我們可以把這樣方法封裝在自己的工具類中。
缺點(diǎn)
1. 類如果不含有公有的或者受保護(hù)的構(gòu)造方法帅腌,就不能被繼承驰弄。如果使用靜態(tài)工廠方法獲得實(shí)例,而不提供公有的構(gòu)造方法速客,把構(gòu)造方法寫為私有private
戚篙,那么該類就不能被繼承擴(kuò)展,這就是使用復(fù)合而不是繼承來擴(kuò)展類了溺职。
2.與其他的靜態(tài)方法實(shí)際上沒有任何區(qū)別岔擂。靜態(tài)工廠方法其實(shí)和其他普通的靜態(tài)方法是一樣的位喂,如果沒有加以說明,兩者不能很好被區(qū)分開來乱灵,會(huì)造成使用者不知道怎么獲取該類的實(shí)例塑崖,而且不能清晰查明該類是如何被實(shí)例化的。
簡而言之痛倚,靜態(tài)工廠方法和公有構(gòu)造方法都各有用處规婆,我們需要理解它們各自的長處。靜態(tài)工廠通常更加合適蝉稳,因此切忌第一反應(yīng)就是提供公有的構(gòu)造器抒蚜,而不先考慮靜態(tài)工廠。
參考
《Effective Java 中文版 第2版》