- Consider static factory method instead of constructors
- 考慮使用靜態(tài)工廠模式替代構(gòu)造函數(shù)
要點(diǎn)回顧
- 靜態(tài)工廠模式優(yōu)點(diǎn)
- 可指定具有特定含義的函數(shù)名
- 被調(diào)用時無需每次都new新的對象
- 可構(gòu)造子類對象
- 構(gòu)造對象對外封閉
- 構(gòu)建靜態(tài)工廠函數(shù)中可以不構(gòu)造返回的實(shí)例
- 靜態(tài)工廠模式缺點(diǎn)
- 只提供靜態(tài)工廠方法的類無法被繼承
- 靜態(tài)工廠方法不顯而易見
筆記細(xì)節(jié)
1.1 可指定具有特定含義的函數(shù)名
考慮到某個class會有多個構(gòu)造函數(shù)萧吠,他們帶有不同數(shù)量狞膘,不同類型的參數(shù)奈懒。在使用當(dāng)中犬钢,我們很容易混淆這些構(gòu)造函數(shù)及參數(shù)的含義赂毯。改為使用靜態(tài)工廠模式構(gòu)建實(shí)例,可通過恰當(dāng)?shù)暮瘮?shù)名來構(gòu)建易于區(qū)分的不同種實(shí)例。
例如:
public class Machine {
private boolean on;
private boolean charged;
public Machine(boolean on, boolean charged) {
this.on = on;
this.charged = charged;
}
public Machine(boolean on) {
this.on = on
this.charged = false
}
public static Machine newChargedMachine(boolean on) {
return new Machine(on, true);
}
public static Machine newUnchargedMachine(boolean on) {
return new Machine(on);
}
}
當(dāng)使用構(gòu)造函數(shù)構(gòu)建實(shí)例時
Machine m = new Machine(false, true);
很難辨認(rèn)出第一個與第二個參數(shù)的具體含義。
當(dāng)我們引入靜態(tài)工廠模式
Machine m = Machine.newChargedMachine(true);
很容易通過調(diào)用的方法名來區(qū)分出構(gòu)造的實(shí)例
1.2 被調(diào)用時無需每次都new新的對象
當(dāng)我們希望重復(fù)利用已構(gòu)建的實(shí)例庐镐,避免重復(fù)構(gòu)建實(shí)例時,我們可以使用singleton模式变逃。例如最簡單的singleton模式:
public class Singleton {
public static final Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
1.3 可構(gòu)造子類對象
通過靜態(tài)工廠模式在父類中構(gòu)造子類對象
public class Animal {
public static Animal newDog() {
return new Dog();
}
public static Animal newCat() {
return new Cat();
}
}
public class Dog extends Animal {}
public class Cat extends Animal {}
1.4 構(gòu)造對象對外封閉
靜態(tài)工廠模式可在對外封閉的情況構(gòu)建新的或者修改現(xiàn)有的子類對象必逆,使用者無需過多了解具體類及實(shí)現(xiàn)。java.util.Collections
充分體現(xiàn)了這一點(diǎn)揽乱。當(dāng)我們需要構(gòu)造一個恒定為空的List時名眉,我們只需調(diào)用Collections
內(nèi)的一個靜態(tài)方法而無需去了解EmptyList
是怎樣的一個子類
List emptyList = Collections.emptyList()
1.5 構(gòu)建靜態(tài)工廠函數(shù)中可以不構(gòu)造返回的實(shí)例
在靜態(tài)工廠中,我們甚至可以只表明返回接口的函數(shù)凰棉,不構(gòu)造需要返回的實(shí)例损拢。而是在運(yùn)行時動態(tài)的載入實(shí)例并返回。
public static MyInterface getMyInterfaceInstance() {
//load instance dynamically and return it.
}
參考stackoverflow:https://stackoverflow.com/questions/53240626/what-does-static-factories-returned-object-need-not-exist-mean
2.1 只提供靜態(tài)工廠方法的類無法被繼承
如果只提供靜態(tài)工廠方法構(gòu)造實(shí)例而沒有public或者protected的構(gòu)造函數(shù)撒犀,該類將無法被繼承福压。這是一個有爭議的缺點(diǎn)因?yàn)殡m然繼承可以復(fù)用大量代碼,使結(jié)構(gòu)更為清晰化或舞。冗雜與不恰當(dāng)?shù)睦^承有時反而會造成代碼的過度包裝與復(fù)雜化荆姆。
2.2 靜態(tài)工廠方法不顯而易見
在文檔中,靜態(tài)工廠方法沒有構(gòu)造函數(shù)那樣顯而易見映凳,它沒有固定的命名格式胆筒。有時,你需要仔細(xì)閱讀文檔才能發(fā)現(xiàn)某種靜態(tài)工廠方法诈豌。為了彌補(bǔ)這個缺點(diǎn)仆救,多使用一些慣用的命名規(guī)則:
- from - 類型之間的轉(zhuǎn)化,往往只有一個參數(shù)
- of - 用于構(gòu)造某種類型的組合矫渔,由多個相同類型參數(shù)組成
- valueOf - from的另一種寫法
- instance/getInstance - 返回一個實(shí)例彤蔽,若帶有參數(shù),參數(shù)常表明實(shí)例的某些特征選項(xiàng)
- create/newInstance - 與 instance/getInstance 類似蚌斩,但保證new出一個新的實(shí)例
-
getType - 類似 instance/getInstance铆惑,但往往會構(gòu)造另一個類的實(shí)例范嘱,例如
Files.getFileStore(path);
-
newType - 類似 create/newInstance,但往往會構(gòu)造另一個類的實(shí)例员魏,例如
BufferedReader br = Files.newBufferedReader(path);
- type - 類似 getType 和 newType