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

Eclipse 3.1 深度體驗 J2SE 5.0 註解類型 (6):以註解替代 Visitor 模式實現靈活資料匯出

     編輯:J2SE

Visitor 模式傳統實作痛點

在 J2SE 5.0 之前,為現有類別階層新增操作(如匯出)常用 Visitor 模式:


// Employee 階層需新增 accept 方法
public abstract class Employee {
    public abstract void accept(Exporter visitor);
}

// 每個具體類別實作雙重分派
public class Regular extends Employee {
    public void accept(Exporter v) { v.visit(this); }
}

// Exporter 介面需針對每個具體類別定義 visit 多載
public interface Exporter {
    void visit(Regular e);
    void visit(Vendor e);
    void visit(Contractor e);
    // 新增 Employee 子類別 → 必須修改 Exporter 介面及所有實作!
}

核心缺陷:違反開放封閉原則——新增匯出格式需修改 Exporter 介面,新增 Employee 子類別需修改 Exporter 及所有實作,雙向耦合。

註解驅動方案:零侵入、格式解耦

步驟 1:定義標記註解


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Exportable { }
  • @Target(FIELD):僅允許標註欄位。
  • @Retention(RUNTIME):執行期可透過反射讀取。
  • @Inherited:子類別繼承父類別欄位的註解(針對類別註解有效,欄位註解需配合掃描邏輯)。

步驟 2:領域模型標註欄位


public abstract class Employee {
    @Exportable protected String name;
    @Exportable protected String empNo;
    // 子類別繼承欄位自動擁有註解
}

public class Regular extends Employee {
    @Exportable private String title;
    @Exportable private String phone;
    @Exportable private String location;
    @Exportable private Date hireDate;
    @Exportable private ArrayList members; // 集合欄位特殊處理
}

public class Vendor extends Employee {
    @Exportable private String company;
    @Exportable private String product;
    @Exportable private String id;
}

步驟 3:通用解析器框架(前文 ExportableGenerator)

核心邏輯:掃描類別所有宣告欄位 → 過濾 @Exportable → 依型別分派輸出(簡單欄位/集合遞迴)。詳見前文 ExportableGenerator.genDoc() 實作。

步驟 4:格式特化實作(Strategy)


// 文字格式
public class TXTExportableGenerator extends ExportableGenerator {
    @Override protected void outputSimpleField(PrintWriter out, Field f, Object obj) {
        out.print(f.getName() + "=" + value(f, obj) + ";\n");
    }
    @Override protected void outputFieldHeader(PrintWriter out, Object e) {}
    @Override protected void outputFieldFooter(PrintWriter out, Object e) {}
}

// XML 格式(新增格式零修改現有代碼)
public class XMLExportableGenerator extends ExportableGenerator { /* ... */ }

對比總結:Visitor vs 註解驅動

維度Visitor 模式註解驅動
新增匯出格式修改 Exporter 介面 + 所有實作新增 Generator 子類別(零修改)
新增 Employee 子類別修改 Exporter 介面 + 所有實作無需修改框架,自動掃描新欄位
新增/移除欄位修改對應 visit 方法僅增減欄位上的 @Exportable
程式碼侵入性高(需 accept/visit 雙重分派)低(單一欄位註解)
編譯期型別安全高(介面強制實作)中(執行期反射,可配合測試保證)
效能極高(直接方法呼叫)中(反射開銷,可快取 Field 陣列優化)

適用場景判斷

  • 選 Visitor:操作邏輯極其複雜、需極致效能、類別階層穩定、團隊熟悉雙重分派。
  • 選註解驅動:操作為「資料序列化/匯出/驗證/文件化」等結構化任務、欄位/格式頻繁變動、追求開發效率與維護彈性。

Eclipse 3.1 開發體驗

  • Annotation 定義精靈:New → Annotation 自動生成 @interface 骨架,游標定位於元註解區。
  • @Target 驗證:將 @Exportable 加在方法上 → 即時紅線「Annotation type not applicable to method」。
  • 反射掃描代碼模板:輸入 isAnnotationPresent 觸發內容輔助,自動補全泛型參數。
  • 快速實作抽象方法:建立 Generator 子類別時 Ctrl+1 一鍵生成三個 output... 方法存根。

總結

註解類型配合反射,提供了一種宣告式、零侵入、格式解耦的替代方案,在「資料驅動操作」場景下完美替代 Visitor 模式,符合開放封閉原則,大幅降低維護成本。Eclipse 3.1 的工具鏈讓這種模式的開發門檻極低,值得成為現代 Java 開發者的標準工具箱之一。

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