ps:代碼后期貼。
靜態(tài)工廠(static factory methon)和構(gòu)造器共同局限性:不能很好的擴(kuò)展到大量的可選參數(shù)。
一般情況下很多程序員使用重疊構(gòu)造器模式(telescoping constructor pattern)
優(yōu)點(diǎn):易于編寫(xiě)、易于調(diào)用,參數(shù)數(shù)量較少時(shí)適用。
缺點(diǎn):參數(shù)過(guò)多時(shí)容易失控,比如類型相同的參數(shù),不小心顛倒了其中兩個(gè)參數(shù)的位置,編譯時(shí)不會(huì)報(bào)錯(cuò),而實(shí)際上運(yùn)行時(shí)就會(huì)出現(xiàn)錯(cuò)誤。
第二種方法,JavaBeans模式(JavaBeans pattern)
實(shí)現(xiàn)過(guò)程:使用無(wú)參構(gòu)造器創(chuàng)建對(duì)象,調(diào)用setter方法設(shè)置必要/可選參數(shù)。
優(yōu)點(diǎn):創(chuàng)建實(shí)例容易,代碼可讀性高。
缺點(diǎn):
1、構(gòu)造對(duì)象的過(guò)程被分成了幾個(gè)調(diào)用導(dǎo)致JavaBean可能處于不一致的狀態(tài)。類無(wú)法通過(guò)校驗(yàn)構(gòu)造器參數(shù)的有效性來(lái)保證一致性,導(dǎo)致調(diào)試比較困難。
2、JavaBeans模式阻止了把類做成不可變的可能,會(huì)導(dǎo)致線程不安全,需要額外的控制來(lái)保持線程安全(在構(gòu)造完成前手工“凍結(jié)”對(duì)象,但這個(gè)方式很蠢而且無(wú)法編譯器無(wú)法確保程序員是否在使用之前先在對(duì)象上調(diào)用freeze方法)。
第三種方法,Builder模式(Builder Pattern)即建造者模式或者生成器模式,既能保證像重疊構(gòu)造器模式那樣的安全性,又能保證像JavaBeans模式那樣的可讀性。
實(shí)現(xiàn)過(guò)程:不直接生成想要的對(duì)象,使用構(gòu)造器/靜態(tài)工廠來(lái)生成帶有必要參數(shù)的builder對(duì)象,然后在builder對(duì)象上調(diào)用類似setter的方法,設(shè)置可選參數(shù),最后調(diào)用無(wú)參的build方法來(lái)生成不可變的對(duì)象。
優(yōu)點(diǎn):
1、調(diào)用會(huì)很容易,且可讀性高。
2、比構(gòu)造器好的是,可以有多個(gè)可變參數(shù)。而構(gòu)造器只能有一個(gè)可變參數(shù)。
3、可利用單個(gè)builder構(gòu)建多個(gè)對(duì)象。builder的參數(shù)可以在創(chuàng)建對(duì)象期間進(jìn)行調(diào)整,且可自動(dòng)填充某些域(比如每次創(chuàng)建對(duì)象時(shí)自動(dòng)增添序列號(hào))。
4、可對(duì)參數(shù)強(qiáng)加約束條件。方法一:build方法中檢驗(yàn)這些約束條件,在對(duì)象域中進(jìn)行檢驗(yàn),如果違反了約束條件,build方法拋出IllegalStateException。方法二:用多個(gè)setter方法對(duì)某個(gè)約束條件必須持有的所有參數(shù)進(jìn)行檢查,如果不滿足,setter方法拋出IllegalStateException。好處就是在setter中就可以檢驗(yàn)二不是等build時(shí)才發(fā)現(xiàn)錯(cuò)誤。
缺點(diǎn):
1、有額外的開(kāi)銷。為了創(chuàng)建對(duì)象需要先新建builder,雖然開(kāi)銷比較小,但是在十分注重性能的情況下會(huì)成為問(wèn)題。
2、代碼冗長(zhǎng),因此只適合4個(gè)或者更多參數(shù)的情況。但是如果預(yù)料到將來(lái)可能有更多的參數(shù),推薦在一開(kāi)始的時(shí)候就使用建造者模式,因?yàn)榈鹊綄?shí)際出現(xiàn)多個(gè)參數(shù)時(shí)再添加,就會(huì)變得難看,因?yàn)橛幸恍┡f的構(gòu)造器或者靜態(tài)工廠。