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

Java 設計模式實戰:訪問者模式深度解析與代碼實現

     編輯:Java 相關知識

Java 設計模式實戰:訪問者模式深度解析

訪問者模式屬於行為型模式,其核心思想是將數據結構與數據操作分離:在不修改數據結構的前提下,為其動態添加新的操作邏輯。本文通過「花朵與訪問者」經典案例,深度解析模式結構、角色職責、代碼實現及適用場景。

模式結構與角色

訪問者模式結構圖

角色職責對應代碼
Visitor (抽象訪問者)聲明訪問各元素的操作介面interface Visitor { visit(Gladiolus); visit(Chrysanthemum); }
ConcreteVisitor (具體訪問者)實現具體訪問邏輯StringVisitor (獲取名稱), BeeVisitor (模擬蜜蜂授粉)
Visitable/Element (抽象元素)聲明 accept(Visitor) 方法interface Flower { accept(Visitor); }
ConcreteElement (具體元素)實現 accept,調用 visitor.visit(this)Gladiolus (劍蘭), Chrysanthemum (菊花)
ObjectStructure (對象結構)管理元素集合,提供遍歷入口List<Flower> + 迭代器遍歷

核心代碼實現

1. 訪問者介面與實現

// 抽象訪問者
interface Visitor {
    void visit(Gladiolus g);
    void visit(Chrysanthemum c);
}

// 具體訪問者 1:獲取花名字符串
class StringVisitor implements Visitor {
    private String result;
    public String toString() { return result; }
    public void visit(Gladiolus g) { result = "Gladiolus"; }
    public void visit(Chrysanthemum c) { result = "Chrysanthemum"; }
}

// 具體訪問者 2:模擬蜜蜂訪問行為
class BeeVisitor implements Visitor {
    public void visit(Gladiolus g) { System.out.println("蜜蜂來訪問劍蘭"); }
    public void visit(Chrysanthemum c) { System.out.println("蜜蜂來訪問菊花"); }
}

2. 元素介面與實現

// 抽象元素
interface Flower {
    void accept(Visitor v);
}

// 具體元素:菊花
class Chrysanthemum implements Flower {
    public void accept(Visitor v) { v.visit(this); } // 關鍵:雙分派入口
}

// 具體元素:劍蘭
class Gladiolus implements Flower {
    public void accept(Visitor v) { v.visit(this); }
}

3. 對象結構與客戶端測試

// 花朵生成器 (模擬對象結構)
class FlowerGenerator {
    private static Random rand = new Random();
    public static Flower newFlower() {
        return rand.nextInt(2) == 0 ? new Gladiolus() : new Chrysanthemum();
    }
}

public class VisitorPatternDemo {
    public static void main(String[] args) {
        // 1. 構建對象結構
        List<Flower> flowers = new ArrayList<>();
        for (int i = 0; i < 10; i++) flowers.add(FlowerGenerator.newFlower());

        // 2. 訪問者 1:統計花名
        Visitor nameVisitor = new StringVisitor();
        for (Flower f : flowers) {
            f.accept(nameVisitor);
            System.out.println(nameVisitor);
        }
        System.out.println("---------------");

        // 3. 訪問者 2:模擬蜜蜂行為 (新增操作,無需修改 Flower 類)
        Visitor beeVisitor = new BeeVisitor();
        for (Flower f : flowers) {
            f.accept(beeVisitor);
        }
    }
}

運行輸出

Gladiolus
Chrysanthemum
Chrysanthemum
Gladiolus
...
---------------
蜜蜂來訪問劍蘭
蜜蜂來訪問菊花
蜜蜂來訪問菊花
蜜蜂來訪問劍蘭
...

核心機制:雙分派

訪問者模式本質上實現了雙分派:

  1. 第一次分派:客戶端調用 element.accept(visitor),根據元素類型 (Gladiolus/Chrysanthemum) 分派到具體 accept 方法。
  2. 第二次分派:accept 內部調用 visitor.visit(this),根據訪問者類型 (StringVisitor/BeeVisitor) 分派到具體 visit 重載方法。

Java 單分派特性下,通過「元素主動調用訪問者方法並傳遞 this」曲線實現雙分派。

適用場景 (GoF 經典判準)

何時使用訪問者模式?

  1. 對象結構包含多類接口不同的對象,需執行依賴具體類的操作 (如編譯器 AST 處理)。
  2. 需對對象結構執行多種不相關操作,避免操作「污染」元素類 (如導出 XML/JSON/PDF、類圖生成)。
  3. 對象結構被多應用共享,每應用僅需子集操作 (訪問者封裝應用相關操作)。
  4. 對象結構類穩定,但頻繁添加新操作 (修改結構類代價大,訪問者擴展廉價)。
反模式警示:若對象結構類頻繁變動 (新增/刪除元素類),訪問者介面需頻繁修改,破壞封裝,不如直接在元素類中添加方法。

優缺點總結

優點缺點
符合單一職責:操作邏輯集中在訪問者 增加新元素類困難:需修改 Visitor 介面及所有實現
開閉原則:新增操作無需修改元素類 破壞封裝:訪問者需訪問元素內部狀態 (常需暴露 getter)
複用性:同一對象結構可復用多訪問者 適用性受限:僅適合穩定結構、變化操作場景

實戰應用場景

  • 編譯器/解析器:AST 節點結構固定,操作多樣 (類型檢查、代碼生成、優化、pretty-print)。
  • 文檔導出框架:文檔模型 (標題/段落/表格) 穩定,導出格式多變 (PDF/Word/HTML/Markdown)。
  • 靜態代碼分析工具:代碼元素結構固定,檢查規則不斷增加 (SonarQube 規則引擎)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved