首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2SE

Eclipse 3.1 深度體驗 J2SE 5.0 註解類型 (8):ExportableGenerator 框架核心與測試驅動完整代碼

     編輯:J2SE

測試入口:TestExportable


public class TestExportable {
    public static void main(String[] args) {
        // 建構員工物件圖(含巢狀成員)
        Regular emp = new Regular("Catherine", "IBM", "Software Engineer", "82888288", "BJ", new Date());
        emp.addMember(new Vendor("Steve", "IBM", "PVC", "8"));
        emp.addMember(new Vendor("Steve", "IBM", "PVC", "8"));
        emp.addMember(new Contractor("Joe", "IBM"));
        emp.addMember(new Supplemental("Linda", "IBM", "8"));

        try (PrintWriter pw = new PrintWriter(new FileOutputStream("C:\\test.output", true))) {
            ExportableGenerator gen = new TXTExportableGenerator(pw);
            gen.genDoc(emp, 0);
            gen.flush();
        } catch (FileNotFoundException e) { e.printStackTrace(); }
    }
}

核心框架:ExportableGenerator(抽象基類)


public abstract class ExportableGenerator {
    protected PrintWriter out;

    public ExportableGenerator(PrintWriter out) { this.out = out; }

    // 主入口:遞迴處理物件圖
    public void genDoc(Employee e, int tagNum) {
        Class<?> clazz = e.getClass();
        Field[] fields = clazz.getDeclaredFields();
        outputFieldHeader(out, e);

        for (Field f : fields) {
            if (f.isAnnotationPresent(Exportable.class)) {
                if (f.getType() != ArrayList.class) {
                    // 簡單欄位:輸出縮排 + 欄位內容
                    for (int i = 0; i < tagNum; i++) out.print("***");
                    outputSimpleField(out, f, e);
                } else {
                    // 集合欄位:遞迴處理每個成員
                    try {
                        @SuppressWarnings("unchecked")
                        ArrayList<Employee> team = (ArrayList<Employee>) f.get(e);
                        out.println("-----------------------------");
                        for (Employee member : team) {
                            genDoc(member, tagNum + 1);
                            out.println("-----------------------------");
                        }
                    } catch (IllegalAccessException ex) { ex.printStackTrace(); }
                }
            }
        }
        outputFieldFooter(out, e);
    }

    public void flush() {
        out.flush();
        out.close();
    }

    // 型別安全的值提取與格式化
    protected String value(Field f, Object obj) {
        Class<?> type = f.getType();
        try {
            if (type == String.class) return (String) f.get(obj);
            if (type == Date.class) return DateFormat.getDateInstance().format((Date) f.get(obj));
        } catch (IllegalAccessException e) { e.printStackTrace(); }
        return f.getName(); // fallback
    }

    // 留給子類別實作的三個擴充點
    protected abstract void outputSimpleField(PrintWriter out, Field f, Object obj);
    protected abstract void outputFieldHeader(PrintWriter out, Object e);
    protected abstract void outputFieldFooter(PrintWriter out, Object e);
}

架構設計精華

模式體現位置效益
Template MethodgenDoc 定義遞迴骨架,outputSimpleField 等延遲到子類演算法骨架固定,格式細節可變
Reflection + Annotationf.isAnnotationPresent(Exportable.class)零硬編碼欄位名,新增欄位只加註解
Visitor 虛擬化遞迴 genDoc 替代雙重分派無需修改 Employee 階層即可新增匯出格式
StrategyTXTExportableGenerator / XMLExportableGenerator格式切換僅需注入不同 Generator

關鍵技術細節

  1. 欄位存取權限:getDeclaredFields() 取得私有欄位,需配合 f.setAccessible(true)(此處省略,實際專案必加)。
  2. 泛型擦除應對:ArrayList 執行期無型別參數,用 f.getType() != ArrayList.class 判斷集合欄位。
  3. 縮排層級:tagNum 參數追蹤遞迴深度,產生視覺層次。
  4. 日期格式化:DateFormat.getDateInstance() 依區域預設格式化。

擴充範例:XML 格式產生器


public class XMLExportableGenerator extends ExportableGenerator {
    public XMLExportableGenerator(PrintWriter out) { super(out); }

    @Override protected void outputFieldHeader(PrintWriter out, Object e) {
        out.println("<" + e.getClass().getSimpleName() + ">");
    }
    @Override protected void outputFieldFooter(PrintWriter out, Object e) {
        out.println("");
    }
    @Override protected void outputSimpleField(PrintWriter out, Field f, Object obj) {
        out.print("  <" + f.getName() + ">");
        out.print(value(f, obj));
        out.println("");
    }
}

僅 15 行代碼即實現完整 XML 匯出,展現開放封閉原則威力。

Eclipse 3.1 開發加速

  • 快速產生抽象方法:建立子類別時,Ctrl+1 → Implement abstract methods 一鍵生成三個 output... 存根。
  • 型別安全轉型輔助:(ArrayList<Employee>) 附帶 @SuppressWarnings("unchecked"),Eclipse 自動建議加上。
  • 反射 API 內容輔助:Field. 顯示 isAnnotationPresent、getType、get 等關鍵方法。

總結

ExportableGenerator 框架以反射掃描註解 + 模板方法遞迴 + 策略模式格式化三重模式結合,實現「欄位級宣告、格式零耦合、結構自動遞迴」的通用匯出引擎。測試代碼展示完整物件圖建構與輸出驗證流程,為後續 XML/JSON/CSV 多格式擴充奠定堅實基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved