訪問者模式封裝作用於數據結構中各元素的操作,使在不修改數據結構前提下定義新操作成為可能。它是行為型模式中最複雜但也最強大的模式之一,核心思想是雙分派。
visit(ConcreteElement) 重載方法,定義可訪問元素類型。accept(Visitor) 方法,規範接受訪問行為。accept 調用 visitor.visit(this),實現雙分派第一步。interface Visitor {
void visit(ElementA a);
void visit(ElementB b);
}
interface Element { void accept(Visitor v); }
class ElementA implements Element {
public void accept(Visitor v) { v.visit(this); }
public void doA() { System.out.println("ElementA"); }
}
class ElementB implements Element {
public void accept(Visitor v) { v.visit(this); }
public void doB() { System.out.println("ElementB"); }
}
class ConcreteVisitor implements Visitor {
public void visit(ElementA a) { a.doA(); /* 操作A邏輯 */ }
public void visit(ElementB b) { b.doB(); /* 操作B邏輯 */ }
}
class ObjectStructure {
List<Element> elements = new ArrayList<>();
public void accept(Visitor v) { elements.forEach(e -> e.accept(v)); }
}
| 優點 | 缺點 |
|---|---|
| 符合單一職責:操作邏輯集中在訪問者中 | 增加新元素類極難:需修改所有訪問者接口及實現 |
| 擴展性好:新增操作只需新增訪問者類 | 破壞封裝:訪問者需訪問元素內部細節 |
| 復用性強:多對象共享同一訪問邏輯 | 適用場景窄:元素結構穩定、操作易變時才適合 |
GoF 評價:「大多數情況下你不需要訪問者模式,但當你需要時,你真的需要它。」它是針對「操作易變、結構穩定」場景的終極武器,濫用則會帶來維護噩夢。決策前請三思:元素結構是否真正穩定?操作變化是否頻繁?