程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 漫談Java實例化類,漫談java實例

漫談Java實例化類,漫談java實例

編輯:JAVA綜合教程

漫談Java實例化類,漫談java實例


    Java 中實例化類的動作,你是否還是一成不變 new 對應對象呢?

    經手的項目多了,代碼編寫量自然會增加,漸漸的會對設計模式產生感覺。

    怎樣使書寫出來的類實例化動作,高內聚,低耦合,又兼具一定的擴展能力呢?

    本文試圖從幾段鮮活的代碼入手,給大家呈現不一樣的 Java 實例化類。

    下面代碼取自 com.google.zxing 源碼實現:

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類,其中定義了不同類型的條形碼的屬性。
  • 調用 MultiFormatWriter.encode()  根據入參 BarcodeFormat.xx 在枚舉類中的序號,來實例化具體的類。
  •        switch(format.ordinal()) {
            case 1:
                writer = new AztecWriter();
                break;
            case 2:
                writer = new CodaBarWriter();
                break;
            case 3:
                writer = new Code39Writer();
                break;
           ...............
  • 這些條形碼 Writer 類,同時都實現了抽象接口 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 類內部根據不同類型的條形碼規則,進行不同的邏輯。
  • 使用者不需要過多的關注內部的實現,需要產生什麼樣子的條形碼,入參選用合適的條形碼類型即可,筆者上述的例子裡面實現的是二維碼。

      在來看經典 MVC 框架 Webwork 動態實例化類的一段方法代碼:

   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 應該是如雷貫耳,Struts2 核心改寫自 Webwork。
  • 上述源碼提供的功能為實例化用戶自己定義的 配置文件讀取類,該定義是在配置文件當中。
  • 源碼作者在這裡使用 Thread.currentThread().getContextClassLoader().loadClass(className) 線程中類加載器,動態實例化自定義配置文件讀取類,可謂是效率最高的一種做法。
  • 類加載器的委托鏈:SystemClassloader -> ExtensionClassloader -> BootstrapClassloader 
  • 委派鏈左邊的ClassLoader就可以很自然的使用右邊的ClassLoader所加載的類,類加載的機制為判斷自已是否加載該類,沒有在詢問上級。
  • 而這三個類加載器分別對應著編譯器去尋找類文件的優先級別和不同的路徑:
  • BootClassLoader  它是用C++編寫的,從%jre%/lib目錄中加載類,或者運行時用-Xbootclasspath指定目錄來加載。是編譯器最優先尋找class的地方 
  • ExtClassLoader  從%jre%/lib/ext目錄加載類,或者運行時用-Djava.ext.dirs制定目錄來加載。是編譯器次優先尋找class的地方 
  • SystemClassloader 也就是我們常說的AppClassloader ,它對應當前路徑,所以也是編譯器默認找class的地方。
  • 平時項目中使用的 Class.forname() 會從 BootstrapClassloader 開始詢問,是最消耗資源的。
  • 源碼作者在這裡采用線程類加載器,對應為 SystemClassloader ,效率無疑是最高的。

      夜已經深了,看客老爺看完之後是否有一點點的感覺呢。

      如果你不喜歡將時間萬物抽象到計算機的世界,或許程序員只是你謀生的手段,你可能體會不到代碼的美麗。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved