更新時間:2022-11-24 10:00:59 來源:動力節(jié)點 瀏覽1239次
靜態(tài)工廠模式是一種改進的獲取實例的方法。
通常我們會使用new關(guān)鍵字調(diào)用類的構(gòu)造方法來創(chuàng)建一個對象,靜態(tài)工廠模式相對于傳統(tǒng)的創(chuàng)建對象的方式有以下優(yōu)點:
當一個類的構(gòu)造方法有非常多的參數(shù)或被重載過很多次的話,因為JAVA對構(gòu)造方法命名的規(guī)定(與類名相同),我們必須編寫多個命名相同但實際不同的構(gòu)造函數(shù),在創(chuàng)建對象時很難區(qū)分我們應該調(diào)用哪個構(gòu)造方法。
比如在實際生產(chǎn)中,我們會經(jīng)常見到以下方法:
newInstance():獲取一個新的對象
valueOf():獲取一個值為..的對象
getInstance():獲取一個對象緩存池中的對象或單例對象
甚至我們可以更加細分,比如有一個Person類,我們想根據(jù)年齡來獲取不同的對象,則可有如下靜態(tài)工廠方法:
getChild():獲取一個兒童對象
getOld():獲取一個老年對象
getYouth():獲取一個青年對象
等等,比起new關(guān)鍵字,顯然使用上述方法獲取對象更加具有可讀性,使我們對創(chuàng)造的實例類型更可控。
當一個類的對象會被頻繁使用,且沒有必要在每次使用時都生成新的對象時,我們會考慮使用單例模式。單例模式大多是由靜態(tài)工廠實現(xiàn)的,我們可以在工廠內(nèi)部控制新生成實例或返回已有實例。
比如,DCL單例模式獲取對象時就是采用了靜態(tài)工廠:
public class Car {
//構(gòu)造函數(shù)私有,禁止通過常規(guī)方式實例化
private Car(){}
//單例對象的引用
static volatile Car car=null;
//DCL獲取單例對象,靜態(tài)工廠方法
static Car getInstance(){
if(car==null){
synchronized(Car.class){
if(car==null){
car=new Car();
}
}
}
return car;
}
private Object readResolve() {
return getCar();
}
}
我們可以通過靜態(tài)工廠返回一個類型的所有子類,可以更加靈活的獲取實例。這也符合了兩大設(shè)計原則:里氏替換原則與依賴倒置原則。即所有父類可以出現(xiàn)的地方子類也可以出現(xiàn),以及類的使用方不應該依賴具體的實現(xiàn)類,而應該依賴繼承鏈的頂端(接口或抽象類),即依賴抽象。
從Car中我們可以獲取Bus和Taxi兩個子類的實例,其它類在使用時只需維護一個Car的引用,至于具體用Bus還是用Taxi只由獲取實例的那行代碼決定,我們可以在只更換實例的獲取而不改變其它代碼(業(yè)務邏輯)的情況下修改代碼。
public class Car{
public static Car getBus(){
return new Bus();
}
public static Car getTaxi(){
return new Taxi();
}
}
public class bus extends Car{
}
public class taxi extends Car{
}
這條主要是針對帶泛型類的繁瑣聲明而說的,需要重復書寫兩次泛型參數(shù):
Map<String,Date> map = new HashMap<String,Date>();
不過自從 java7 開始,這種方式已經(jīng)被優(yōu)化過了 —— 對于一個已知類型的變量進行賦值時,由于泛型參數(shù)是可以被推導出,所以可以在創(chuàng)建實例時省略掉泛型參數(shù)。
Map<String,Date> map = new HashMap<>();
所以這個問題實際上已經(jīng)不存在了。大家如果想了解更多相關(guān)知識,不妨來關(guān)注一下本站的Java設(shè)計模式,里面還有更豐富的知識等著大家去學習,相信對大家一定能夠有所幫助。