?? static方法.txt
字號:
Java面向?qū)ο缶幊?靜態(tài)工廠方法
Java面向?qū)ο缶幊? 靜態(tài)工廠方法
創(chuàng)建類的實例的最常見的方式是用new語句調(diào)用類的構(gòu)造方法。在這種情況下,程序可以創(chuàng)建類的任意多個實例,每執(zhí)行一條new語句,都會導(dǎo)致Java虛擬機的堆區(qū)中產(chǎn)生一個新的對象。假如類需要進一步封裝創(chuàng)建自身實例的細(xì)節(jié),并且控制自身實例的數(shù)目,那么可以提供靜態(tài)工廠方法。
例如Class實例是Java虛擬機在加載一個類時自動創(chuàng)建的,程序無法用new語句創(chuàng)建 java.lang.Class類的實例,因為Class類沒有提供public類型的構(gòu)造方法。為了使程序能獲得代表某個類的Class實例,在 Class類中提供了靜態(tài)工廠方法forName(String name),它的使用方式如下:
Class c=Class.forName("Sample"); //返回代表Sample類的實例
靜態(tài)工廠方法與用new語句調(diào)用的構(gòu)造方法相比,有以下區(qū)別。
(1)構(gòu)造方法的名字必須與類名相同。這一特性的優(yōu)點是符合Java語言的規(guī)范,缺點是類的所有重載的構(gòu)造方法的名字都相同,不能從名字上區(qū)分每個重載方法,容易引起混淆。
靜態(tài)工廠方法的方法名可以是任意的,這一特性的優(yōu)點是可以提高程序代碼的可讀性,在方法名中能體現(xiàn)與實例有關(guān)的信息。例如例程11-5的Gender類有兩個靜態(tài)工廠方法:getFemale()和getMale()。
例程11-5 Gender.java
public class Gender{
private String description;
private static final Gender female=new Gender("女");
private static final Gender male=new Gender("男");
private Gender(String description){this.description=description;}
public static Gender getFemale(){
return female;
}
public static Gender getMale(){
return male;
}
public String getDescription(){return description;}
}
這一特性的缺點是與其他的靜態(tài)方法沒有明顯的區(qū)別,使用戶難以識別類中到底哪些靜態(tài)方法專門負(fù)責(zé)返回類的實例。為了減少這一缺點帶來的負(fù)面影響,可以在為靜態(tài)工廠方法命名時盡量遵守約定俗成的規(guī)范,當(dāng)然這不是必需的。目前比較流行的規(guī)范是把靜態(tài)工廠方法命名為 valueOf或者getInstance。
l valueOf:該方法返回的實例與它的參數(shù)具有同樣的值,例如:
Integer a=Integer.valueOf(100); //返回取值為100的Integer對象
從上面代碼可以看出,valueOf()方法能執(zhí)行類型轉(zhuǎn)換操作,在本例中,把int類型的基本數(shù)據(jù)轉(zhuǎn)換為Integer對象。
l getInstance:返回的實例與參數(shù)匹配,例如:
//返回符合中國標(biāo)準(zhǔn)的日歷
Calendar cal=Calendar.getInstance(Locale.CHINA);
(2)每次執(zhí)行new語句時,都會創(chuàng)建一個新的對象。而靜態(tài)工廠方法每次被調(diào)用的時候,是否會創(chuàng)建一個新的對象完全取決于方法的實現(xiàn)。
(3)new語句只能創(chuàng)建當(dāng)前類的實例,而靜態(tài)工廠方法可以返回當(dāng)前類的子類的實例,這一特性可以在創(chuàng)建松耦合的系統(tǒng)接口時發(fā)揮作用,參見本章11.3.5節(jié)(松耦合的系統(tǒng)接口)。
靜態(tài)工廠方法最主要的特點是:每次被調(diào)用的時候,不一定要創(chuàng)建一個新的對象。利用這一特點,靜態(tài)工廠方法可用來創(chuàng)建以下類的實例。
l 單例類:只有惟一的實例的類。
l 枚舉類:實例的數(shù)量有限的類。
l 具有實例緩存的類:能把已經(jīng)創(chuàng)建的實例暫且存放在緩存中的類。
l 具有實例緩存的不可變類:不可變類的實例一旦創(chuàng)建,其屬性值就不會被改變。
在下面幾節(jié),將結(jié)合具體的例子,介紹靜態(tài)工廠方法的用途。
11.3.1 單例(singleton)類
單例類是指僅有一個實例的類。在系統(tǒng)中具有惟一性的組件可作為單例類,這種類的實例通常會占用較多的內(nèi)存,或者實例的初始化過程比較冗長,因此隨意創(chuàng)建這些類的實例會影響系統(tǒng)的性能。
Tips
熟悉Struts和Hibernate軟件的讀者會發(fā)現(xiàn),Struts框架的ActionServlet類就是單例類,此外,Hibernate的SessionFactory和Configuration類也是單例類。
例程11-6的GlobalConfig類就是個單例類,它用來存放軟件系統(tǒng)的配置信息。這些配置信息本來存放在配置文件中,在GlobalConfig類的構(gòu)造方法中會從配置文件中讀取配置信息,并把它存放在properties屬性中。
例程11-6 GlobalConfig.java
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class GlobalConfig {
private static final GlobalConfig INSTANCE=new GlobalConfig();
private Properties properties = new Properies();
private GlobalConfig(){
try{
//加載配置信息
InputStream in=getClass().getResourceAsStream("myapp.properties");
properties.load(in);
in.close();
}catch(IOException e){throw new RuntimeException("加載配置信息失敗");}
}
public static GlobalConfig getInstance(){ //靜態(tài)工廠方法
return INSTANCE;
}
public Properties getProperties() {
return properties;
}
}
實現(xiàn)單例類有兩種方式:
(1)把構(gòu)造方法定義為private類型,提供public static final類型的靜態(tài)變量,該變量引用類的惟一的實例,例如:
public class GlobalConfig {
public static final GlobalConfig INSTANCE =new GlobalConfig();
private GlobalConfig() {…}
…
}
這種方式的優(yōu)點是實現(xiàn)起來比較簡捷,而且類的成員聲明清楚地表明該類是單例類。
(2)把構(gòu)造方法定義為private類型,提供public static類型的靜態(tài)工廠方法,例如:
public class GlobalConfig {
private static final GlobalConfig INSTANCE =new GlobalConfig();
private GlobalConfig() {…
}
public static GlobalConfig getInstance(){return INSTANCE;}
…
}
這種方式的優(yōu)點是可以更靈活地決定如何創(chuàng)建類的實例,在不改變GlobalConfig類的接口的前提下,可以修改靜態(tài)工廠方法getInstance()的實現(xiàn)方式,比如把單例類改為針對每個線程分配一個實例,參見例程11-7。
例程11-7 GlobalConfig.java
package uselocal;
public class GlobalConfig {
private static final ThreadLocal<GlobalConfig> threadConfig=
new ThreadLocal<GlobalConfig>();
private Properties properties = null;
private GlobalConfig(){…}
public static GlobalConfig getInstance(){
GlobalConfig config=threadConfig.get();
if(config==null){
config=new GlobalConfig();
threadConfig.set(config);
}
return config;
}
public Properties getProperties() {return properties; }
}
以上程序用到了ThreadLocal類,關(guān)于它的用法參見第13章的13.14節(jié)(ThreadLocal類)。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -