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

Java 代碼診斷:Depth-First Visitor 模式與 Broken Dispatch 陷阱

     編輯:Java 相關知識

Visitor 模式的擴展性困境

標準 Visitor 要求為每個 Concrete Element 實現 forXxx(),當層次結構龐大且多數類處理邏輯相同時,代碼膨脹嚴重。Depth-First Visitor 將「深度優先遍歷骨架」上移至抽象基類,具體 Visitor 僅實現 forXxxOnly() 組合子節點結果,並可提供 defaultCase() 消除重複。

Depth-First Visitor 實戰

abstract class DepthFirstTreeVisitor implements TreeVisitor {
    public abstract Boolean forLeafOnly(Leaf leaf);
    public abstract Boolean forBranchOnly(Branch branch, Boolean left, Boolean right);
    public Boolean forLeaf(Leaf leaf) { return forLeafOnly(leaf); }
    public Boolean forBranch(Branch branch) {
        Boolean left = branch.left.accept(this);
        Boolean right = branch.right.accept(this);
        return forBranchOnly(branch, left, right);
    }
    // 可選:defaultCase 消除樣板
    public Boolean defaultCase(Tree t) { return false; }
    public Boolean forLeafOnly(Leaf leaf) { return defaultCase(leaf); }
    public Boolean forBranchOnly(Branch b, Boolean l, Boolean r) { return defaultCase(b); }
}

具體 ZeroFinder 僅需關注業務邏輯:

class ZeroFinder extends DepthFirstTreeVisitor {
    public Boolean forBranchOnly(Branch b, Boolean l, Boolean r) {
        if (b.value == 0) return true;
        return l || r;
    }
}

致命陷阱:Broken Dispatch

Depth-First Visitor 引入 forXxx()(遍歷入口)與 forXxxOnly()(業務邏輯)兩組同名不同參數方法。若誤將 forBranchOnly(Branch, Boolean, Boolean) 寫成 forBranch(Branch),將發生**方法重載而非覆寫**。編譯通過,運行時基類 forBranch() 仍被調用,導致業務邏輯失效,極難排查。

防禦建議

  1. 命名規範:forXxx() 僅在基類定義,子類**嚴禁**覆寫;業務邏輯統一放入 forXxxOnly()。
  2. 單元測試先行:每個 Visitor 實現配套測試,覆蓋各元素類型,及早捕獲 Dispatch 失效。
  3. 靜態分析工具:檢測「同名不同參數方法共存」的可疑模式。

Depth-First Visitor 極大簡化了遞歸結構處理,但 Broken Dispatch 是其代價。紀律與測試,是馭之之道。

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