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

Java 設計模式:訪問者模式原理與實戰指南

     編輯:Java 相關知識

模式定義

訪問者模式將數據結構(對象結構)與作用於其上的操作分離,使得在不修改數據類的前提下動態添加新操作。核心雙分派機制:Element.accept(Visitor) → Visitor.visitConcreteElement(this)。

適用場景

  • 對象結構穩定(類型較少變),但操作頻繁擴展(如報表導出、語法樹遍歷、編譯器優化)。
  • 需對異構對象集合(如 List<Object>)進行類型相關處理,避免大量 instanceof 判斷。

核心角色與接口

// 訪問者接口:為每種具體元素聲明 visit 方法
public interface Visitor {
    void visitCollection(Collection c);
    void visitString(String s);
    void visitFloat(Float f);
}

// 可訪問元素接口:定義 accept 入口
public interface Visitable {
    void accept(Visitor v);
}

具體實現示例

1. 具體元素

public class ConcreteElement implements Visitable {
    private String value;
    public ConcreteElement(String v) { this.value = v; }
    public void accept(Visitor v) { v.visitString(this); }
    public String getValue() { return value; }
}

2. 具體訪問者:打印操作

public class PrintVisitor implements Visitor {
    public void visitCollection(Collection c) {
        for (Object o : c) {
            if (o instanceof Visitable) ((Visitable)o).accept(this);
        }
    }
    public void visitString(String s) { System.out.println("'" + s + "'"); }
    public void visitFloat(Float f) { System.out.println(f + "f"); }
}

3. 客戶端調用

List<Visitable> list = Arrays.asList(
    new ConcreteElement("hello"),
    new ConcreteElement("world")
);
Visitor visitor = new PrintVisitor();
for (Visitable e : list) e.accept(visitor);

優缺點分析

優點缺點
符合開閉原則:新增操作只需新增 Visitor 實現,不動 Element 新增 Element 類型需修改 Visitor 接口及所有實現,違反開閉原則
將相關操作集中在 Visitor 中,職責單一 破壞封裝:Visitor 需訪問 Element 內部狀態,可能需暴露 getter
適合對象結構共享多種操作(編譯器、文檔模型) 雙分派增加理解難度,調試較繁瑣

Java 反射增強版(解決 Visitor 接口頻繁變更)

利用反射動態查找 visitXxx 方法,使 Visitor 接口無需預先聲明所有類型:

public class ReflectiveVisitor {
    public void visit(Object element) {
        String methodName = "visit" + element.getClass().getSimpleName();
        try {
            Method m = getClass().getMethod(methodName, element.getClass());
            m.invoke(this, element);
        } catch (NoSuchMethodException e) {
            defaultVisit(element);
        } catch (Exception e) { throw new RuntimeException(e); }
    }
    protected void defaultVisit(Object o) { /* 默認處理 */ }
}

總結

訪問者模式是「操作與數據分離」的經典實踐。在「數據結構穩定、操作多變」場景下極具價值;若數據類型頻繁變更,傾向於在數據類內部定義操作或使用反射增強版。

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