標準 Visitor 要求為每個 Concrete Element 實現 forXxx(),當層次結構龐大且多數類處理邏輯相同時,代碼膨脹嚴重。Depth-First Visitor 將「深度優先遍歷骨架」上移至抽象基類,具體 Visitor 僅實現 forXxxOnly() 組合子節點結果,並可提供 defaultCase() 消除重複。
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;
}
}
Depth-First Visitor 引入 forXxx()(遍歷入口)與 forXxxOnly()(業務邏輯)兩組同名不同參數方法。若誤將 forBranchOnly(Branch, Boolean, Boolean) 寫成 forBranch(Branch),將發生**方法重載而非覆寫**。編譯通過,運行時基類 forBranch() 仍被調用,導致業務邏輯失效,極難排查。
forXxx() 僅在基類定義,子類**嚴禁**覆寫;業務邏輯統一放入 forXxxOnly()。Depth-First Visitor 極大簡化了遞歸結構處理,但 Broken Dispatch 是其代價。紀律與測試,是馭之之道。