什么是靜態(tài)工廠方法
- 在Java中式镐,我們得到類的實例的最常用的方法是使用 new 關鍵字來調用類的構造方法匆骗。
- 每使用一個new語句胶背,JVM就會在內存中的堆中開辟一個空間,然后調用構造方法來初始化成員變量辽社,最后把對象的引用返回給調用方。
靜態(tài)工廠方法的優(yōu)點
1.靜態(tài)工廠方法可以有名稱衡奥。
如果構造器的參數(shù)本身沒有確切地描述正被返回的對象爹袁,那么有適當名稱的靜態(tài)工廠方法會更容易使用,產(chǎn)生的代碼也更易于使用矮固。比如,構造函數(shù)BigInteger(int,int,Random)返回的BigInteger可能是素數(shù)譬淳,但如果使用名為BigInteger.probablePrime的靜態(tài)工廠方法來表示档址,這樣會更加清楚。
一個類只能有一個帶有指定方法簽名的構造函數(shù)邻梆,在我們想要避開這個限制的時候守伸,我們提供兩個構造函數(shù),他們參數(shù)列表只有順序不同浦妄。但這個其實并不是個好方法尼摹,因為我們經(jīng)常會忘記這個參數(shù)的順序,調用了錯誤的構造函數(shù)剂娄。但是我們可以通過使用靜態(tài)工廠方法來解決這個問題蠢涝,如果一個類需要多個帶有相同簽名的構造函數(shù)時,我們可以用不同名稱的靜態(tài)工廠方法來替代構造函數(shù)阅懦,仔細地選擇名稱來突出靜態(tài)工廠方法的區(qū)別和二。
2.靜態(tài)工廠方法不是每次調用,都要創(chuàng)建新的對象耳胎。
不可變類是指實例不能被修改的類惯吕。每個實例中的所有信息都必須在創(chuàng)建時就提供,而且在對象的整個生命周期中還要保持不變怕午。 比如有String废登,基本類型的包裝類,BigInteger郁惜,BigDecimal堡距。
我們使用靜態(tài)工廠方法,可以讓這些不可變類使用預先構建好的實例扳炬,或者將構建好的實例緩存起來吏颖,進行重復利用,從而避免創(chuàng)建不必要的重復對象恨樟。如果程序經(jīng)常請求創(chuàng)建相同的對象半醉,并且創(chuàng)建對象的代價很高,那么這個技術就可以極大地提高性能劝术。
靜態(tài)工廠方法能夠為重復的調用返回相同對象缩多,這樣有助于類總能嚴格在某個時刻哪些實例應該存在呆奕。這樣的類叫做實例受控的類(instance-controlled)。
編寫實例受控的類有幾個原因:
- 實例受控使得類可以確保自己是一個單例類(Singleton)或者是不可實例化的衬吆。
- 使得不可變的類可以確保不會存在兩個相等的實例梁钾。就是當且僅當a == b時,a.equals(b)才為true逊抡。
3.靜態(tài)方法可以返回原類型的任何子類型的對象姆泻,讓我們在選擇返回對象的類時就有了更大的靈活性。
里氏替換原則中說冒嫡, 任何基類可以出現(xiàn)的地方拇勃,子類一定可以出現(xiàn)。只有當衍生類可以替換掉基類孝凌,軟件單位的功能不受到影響時方咆,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為蟀架。
參考別人對這個的解釋
構造方法只能返回確切的自身類型瓣赂,也就是說什么方法的構造函數(shù)會返回什么類型的對象,但是靜態(tài)方法可以靈活的控制返回類型片拍,可以根據(jù)需要來返回需要的子類的實例煌集。
Class Person {
public static Person getInstance(){
return new Person();
// 這里可以改為 return new Player() / Cooker()
}
}
Class Player extends Person{
}
Class Cooker extends Person{
}
比如上面這段代碼,Person 類的靜態(tài)工廠方法可以返回 Person 的實例穆碎,也可以根據(jù)需要返回它的子類 Player 或者 Cooker牙勘。(當然,這只是為了演示所禀,在實際的項目中方面,一個類是不應該依賴于它的子類的。但如果這里的 getInstance () 方法位于其他的類中色徘,就更具有的實際操作意義了)
4.靜態(tài)工廠所返回的類可以隨著每次調用而發(fā)生變化恭金,這取決于靜態(tài)工廠方法的參數(shù)值。
舉的例子是EnumSet褂策,小于64個元素會返回枚舉類型横腿,返回RegularEnumSet實例,用單個long進行支持斤寂;有65個或者更多的元素耿焊,工廠就返回JumboEnumSet實例,用一個long數(shù)組進行支持遍搞。
5.靜態(tài)工廠方法返回的對象所屬的類罗侯,在編寫包含該靜態(tài)工廠方法的類時可以不存在。
靜態(tài)工廠方法的缺點
1.類如果不含public或者protected的構造函數(shù)溪猿,就不能被子類化钩杰。
2.靜態(tài)方法很難被發(fā)現(xiàn)纫塌。
下面是一些被經(jīng)常使用的靜態(tài)工廠方法的名稱:
1.from
//from 類型轉換
//單個參數(shù),返回這個類型中的一個相對應的實例
Date d = Date.from(instant);
2.of
//of 聚合方法
//多個參數(shù)讲弄,返回該類型的一個實例措左,把他們合并起來
Set<Rank> faceCards = EnumSet.of(JACK,QUEEN,KING);
3.valueOf
//valueOf
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
4.instance或者getInstance
//instance或者getInstance
//返回的實例是通過方法的參數(shù)來描述的
StackWalker luke = StackWalker.getInstance(options);
5.create或者newInstance
//create或者newInstance
//像instance或者getInstance方法一樣,但這個方法能夠確保每次調用都返回一個新的實例避除。
Object newArray = Array.newInstance(classObject,arrayLen);
6.getType
//getType Type表示工廠方法返回的對象類型
//像getInstance一樣怎披,在工廠方法處于不同的類中的時候使用
FileStore fs = Files.getFileStore(path);
7.newType
//newType Type表示工廠方法返回的對象類型
//像newInstance一樣,在工廠方法處于不同的類中的時候使用
BufferedReader br = Files.newBufferedReader(path);
8.type
//type
//getType和newType的簡版
List<Complaint> litany = Collections.list(legacyLitany);
靜態(tài)方法和構造函數(shù)都各有用處驹饺,要理解各自的長處钳枕。不要第一反應就直接調用構造函數(shù),要多加考慮再進行使用赏壹。