Java實(shí)例化類詳解
Java 中實(shí)例化類的動作,你是否還是一成不變 new 對應(yīng)對象呢?
經(jīng)手的項(xiàng)目多了,代碼編寫量自然會增加,漸漸的會對設(shè)計模式產(chǎn)生感覺。
怎樣使書寫出來的類實(shí)例化動作,高內(nèi)聚,低耦合,又兼具一定的擴(kuò)展能力呢?
本文試圖從幾段鮮活的代碼入手,給大家呈現(xiàn)不一樣的 Java 實(shí)例化類。
下面代碼取自 com.google.zxing 源碼實(shí)現(xiàn):
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType, ?> hints) throws WriterException {
Object writer;
switch(format.ordinal()) {
case 1:
writer = new AztecWriter();
break;
case 2:
writer = new CodaBarWriter();
break;
case 3:
writer = new Code39Writer();
break;
case 4:
case 10:
case 13:
case 14:
default:
throw new IllegalArgumentException("No encoder available for format " + format);
case 5:
writer = new Code128Writer();
break;
case 6:
writer = new DataMatrixWriter();
break;
case 7:
writer = new EAN8Writer();
break;
case 8:
writer = new EAN13Writer();
break;
case 9:
writer = new ITFWriter();
break;
case 11:
writer = new PDF417Writer();
break;
case 12:
writer = new QRCodeWriter();
break;
case 15:
writer = new UPCAWriter();
break;
case 16:
writer = new UPCEWriter();
}
return ((Writer)writer).encode(contents, format, width, height, hints);
}
其中的 BarcodeFormat 是這樣的:
public enum BarcodeFormat {
AZTEC,
CODABAR,
CODE_39,
CODE_93,
CODE_128,
DATA_MATRIX,
EAN_8,
EAN_13,
ITF,
MAXICODE,
PDF_417,
QR_CODE,
RSS_14,
RSS_EXPANDED,
UPC_A,
UPC_E,
UPC_EAN_EXTENSION;
private BarcodeFormat() {
}
}
源碼提供的功能是將信息通過幾種不同類型條形碼 Wirter 輸出為位矩陣,然后輸出到圖片上面,形成隨處可見的各種類型的條形碼。
BitMatrix bitMatrix = new MultiFormatWriter().encode(_text, BarcodeFormat.QR_CODE, qrcodeWidth, qrcodeHeight, hints);
MatrixToImageWriter.writeToFile(bitMatrix, qrcodeFormat, QrcodeFile);
源碼作者在這里使用了JDK 1.5 中引入的新特性 enum 枚舉類,編寫了BarcodeFormat類,其中定義了不同類型的條形碼的屬性。
調(diào)用 MultiFormatWriter.encode() 根據(jù)入?yún)?BarcodeFormat.xx 在枚舉類中的序號,來實(shí)例化具體的類。
switch(format.ordinal()) {
case 1:
writer = new AztecWriter();
break;
case 2:
writer = new CodaBarWriter();
break;
case 3:
writer = new Code39Writer();
break;
...............
這些條形碼 Writer 類,同時都實(shí)現(xiàn)了抽象接口 Writer 的 兩個encode()方法。
public interface Writer {
BitMatrix encode(String var1, BarcodeFormat var2, int var3, int var4) throws WriterException;
BitMatrix encode(String var1, BarcodeFormat var2, int var3, int var4, Map<EncodeHintType, ?> var5) throws WriterException;
}
具體的條形碼 Wirter 類內(nèi)部根據(jù)不同類型的條形碼規(guī)則,進(jìn)行不同的邏輯。
使用者不需要過多的關(guān)注內(nèi)部的實(shí)現(xiàn),需要產(chǎn)生什么樣子的條形碼,入?yún)⑦x用合適的條形碼類型即可,筆者上述的例子里面實(shí)現(xiàn)的是二維碼。
在來看經(jīng)典 MVC 框架 Webwork 動態(tài)實(shí)例化類的一段方法代碼:
private static Configuration getDefaultConfiguration () {
if (defaultImpl == null) {
defaultImpl = new DefaultConfiguration();
try {
String className = getString("webwork.configuration");
if (!className.equals(defaultImpl.getClass().getName())) {
try {
defaultImpl = (Configuration) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className));
} catch (Exception e) {
LOG.error("Could not instantiate configuration", e);
}
}
return defaultImpl;
} catch (IllegalArgumentException localIllegalArgumentException) {
}
}
}
源碼取自 webwork-core,可能很多看客老爺沒有聽聞 Webwork, 但是對 Struts 應(yīng)該是如雷貫耳,Struts2 核心改寫自 Webwork。
上述源碼提供的功能為實(shí)例化用戶自己定義的 配置文件讀取類,該定義是在配置文件當(dāng)中。
源碼作者在這里使用 Thread.currentThread().getContextClassLoader().loadClass(className) 線程中類加載器,動態(tài)實(shí)例化自定義配置文件讀取類,可謂是效率最高的一種做法。
類加載器的委托鏈:SystemClassloader -> ExtensionClassloader -> BootstrapClassloader
委派鏈左邊的ClassLoader就可以很自然的使用右邊的ClassLoader所加載的類,類加載的機(jī)制為判斷自已是否加載該類,沒有在詢問上級。
而這三個類加載器分別對應(yīng)著編譯器去尋找類文件的優(yōu)先級別和不同的路徑:
- BootClassLoader 它是用C++編寫的,從%jre%/lib目錄中加載類,或者運(yùn)行時用-Xbootclasspath指定目錄來加載。是編譯器最優(yōu)先尋找class的地方
- ExtClassLoader 從%jre%/lib/ext目錄加載類,或者運(yùn)行時用-Djava.ext.dirs制定目錄來加載。是編譯器次優(yōu)先尋找class的地方
- SystemClassloader 也就是我們常說的AppClassloader ,它對應(yīng)當(dāng)前路徑,所以也是編譯器默認(rèn)找class的地方。
平時項(xiàng)目中使用的 Class.forname() 會從 BootstrapClassloader 開始詢問,是最消耗資源的。
源碼作者在這里采用線程類加載器,對應(yīng)為 SystemClassloader ,效率無疑是最高的。
相關(guān)文章
基于SpringBoot2.0默認(rèn)使用Redis連接池的配置操作
這篇文章主要介紹了基于SpringBoot2.0默認(rèn)使用Redis連接池的配置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
SpringBoot 整合Tess4J庫實(shí)現(xiàn)圖片文字識別案例詳解
Tess4J是一個基于Tesseract OCR引擎的Java接口,可以用來識別圖像中的文本,說白了,就是封裝了它的API,讓Java可以直接調(diào)用,今天給大家分享一個SpringBoot整合Tess4j庫實(shí)現(xiàn)圖片文字識別的小案例2023-10-10
Java語言Consistent Hash算法學(xué)習(xí)筆記(代碼示例)
這篇文章主要介紹了Java語言Consistent Hash算法學(xué)習(xí)筆記(代碼示例),分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02
Java ThreadLocal類應(yīng)用實(shí)戰(zhàn)案例分析
這篇文章主要介紹了Java ThreadLocal類應(yīng)用,結(jié)合具體案例形式分析了java ThreadLocal類的功能、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-09-09

