後端開發 設計模式 · 第 24 / 24 篇

訪問者模式:新增功能不動既有架構

訪問者模式 (Visitor Pattern) 讓你在不改變物件結構下新增功能。本文以 C# 遊樂園設施範例,示範如何解耦資料結構與操作邏輯。

哈囉朋友們~今天要介紹的是比較特殊但十分強大的訪問者模式(Visitor),透過這個模式,你可以在不修改物件結構的情況下輕鬆新增功能!

🌟 訪問者模式是什麼?

訪問者模式允許你在不改變現有類別結構的情況下,為類別增加新的操作。

舉個例子,就像遊樂園的各種設施,每個訪客來到遊樂園會玩不同的設施。設施本身不會改變,但每位訪客的行為和感受可能不同,訪客們就是訪問者(Visitor),設施則是被訪問的元素(Element)。


🤔 什麼情況適合使用訪問者模式?

以下情況很適合使用訪問者模式:

  • 當你需要對一個物件結構新增許多不同且不相關的操作。
  • 希望在不修改現有結構的情況下,能輕鬆增加新功能。
  • 當物件結構相對穩定,但操作或功能可能經常變動時。

🎢 C# 訪問者模式範例:遊樂園設施與訪客

這次我們以遊樂園的訪客與設施為例。

🎠 定義元素介面(設施)

/// <summary>
/// 設施介面
/// </summary>
public interface IAmusementFacility
{
    /// <summary>
    /// 接受訪問者
    /// </summary>
    /// <param name="visitor">訪問者</param>
    void Accept(IVisitor visitor);
}

🎡 具體設施類別

/// <summary>
/// 雲霄飛車
/// </summary>
public class RollerCoaster : IAmusementFacility
{
    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

/// <summary>
/// 摩天輪
/// </summary>
public class FerrisWheel : IAmusementFacility
{
    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

👨‍👩‍👧‍👦 定義訪問者介面與具體訪問者

using System;

/// <summary>
/// 訪問者介面
/// </summary>
public interface IVisitor
{
    /// <summary>
    /// 造訪雲霄飛車
    /// </summary>
    /// <param name="rollerCoaster">雲霄飛車</param>
    void Visit(RollerCoaster rollerCoaster);

    /// <summary>
    /// 造訪摩天輪
    /// </summary>
    /// <param name="ferrisWheel">摩天輪</param>
    void Visit(FerrisWheel ferrisWheel);
}

/// <summary>
/// 成人訪客
/// </summary>
public class AdultVisitor : IVisitor
{
    public void Visit(RollerCoaster rollerCoaster)
    {
        Console.WriteLine("成人訪客很享受雲霄飛車的刺激!");
    }

    public void Visit(FerrisWheel ferrisWheel)
    {
        Console.WriteLine("成人訪客悠閒地坐著摩天輪欣賞風景。");
    }
}

/// <summary>
/// 小孩訪客
/// </summary>
public class ChildVisitor : IVisitor
{
    public void Visit(RollerCoaster rollerCoaster)
    {
        Console.WriteLine("小孩訪客覺得雲霄飛車太可怕了!");
    }

    public void Visit(FerrisWheel ferrisWheel)
    {
        Console.WriteLine("小孩訪客開心地乘坐摩天輪。");
    }
}

🚀 實際使用範例

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        List<IAmusementFacility> facilities = new List<IAmusementFacility>
        {
            new RollerCoaster(),
            new FerrisWheel()
        };

        IVisitor adult = new AdultVisitor();
        IVisitor child = new ChildVisitor();

        Console.WriteLine("成人訪客進入遊樂園:");
        foreach (var facility in facilities)
        {
            facility.Accept(adult);
        }

        Console.WriteLine("\n小孩訪客進入遊樂園:");
        foreach (var facility in facilities)
        {
            facility.Accept(child);
        }
    }
}

🎯 執行結果

成人訪客進入遊樂園:
成人訪客很享受雲霄飛車的刺激!
成人訪客悠閒地坐著摩天輪欣賞風景。

小孩訪客進入遊樂園:
小孩訪客覺得雲霄飛車太可怕了!
小孩訪客開心地乘坐摩天輪。

⚠️ 訪問者模式使用注意事項

  • 優點:能輕鬆新增新功能而不影響原有結構,保持系統靈活性。
  • 缺點:新增元素或修改結構會較困難,適合穩定的物件結構。

🎉 結語

恭喜你掌握了訪問者模式(Visitor)!透過這個模式,你的程式能在不改動既有結構的情況下,輕鬆擴充新功能!

繼續追蹤我們的設計模式系列,下篇再見啦~

系列:

讀完了!你覺得這篇如何?

你的回饋會決定下一篇要寫什麼。

還有疑問

Learning path

設計模式

這篇是系列中的第 24 / 24 篇。可以順著列表補完整脈絡,也可以直接跳到需要的段落。

  1. 01 搞懂設計模式到底是什麼?
  2. 02 單例模式:只要一個就夠!
  3. 03 工廠方法模式:點披薩不用親自下廚
  4. 04 抽象工廠模式:系列產品輕鬆生產
  5. 05 原型模式:複製的藝術
  6. 06 建造者模式:一步步完成複雜任務
  7. 07 介面卡模式:讓不相容也能合作
  8. 08 橋接模式:抽象與實作分離
  9. 09 組合模式:樹狀結構的好幫手
  10. 10 裝飾者模式:讓功能自由加點
  11. 11 外觀模式:化繁為簡
  12. 12 享元模式:節省記憶體的利器
  13. 13 代理模式:控制存取的守門員
  14. 14 責任鏈模式:層層把關的處理機制
  15. 15 命令模式:靈活封裝的請求指令
  16. 16 解譯器模式:讓程式聽懂你的指令
  17. 17 迭代器模式:輕鬆遍歷集合元素
  18. 18 中介者模式:管理複雜溝通的好幫手
  19. 19 備忘錄模式:保存與恢復物件狀態
  20. 20 觀察者模式:即時通知的好幫手
  21. 21 狀態模式:依狀態改變行為的祕訣
  22. 22 策略模式:靈活切換行為的好幫手
  23. 23 模板方法模式:固定流程靈活實作
  24. 24 訪問者模式:新增功能不動既有架構 目前閱讀

Further reading

中介者模式:管理複雜溝通的好幫手 封面圖 2025-06-13 中介者模式:管理複雜溝通的好幫手 備忘錄模式:保存與恢復物件狀態 封面圖 2025-06-13 備忘錄模式:保存與恢復物件狀態 模板方法模式:固定流程靈活實作 封面圖 2025-06-13 模板方法模式:固定流程靈活實作

留言討論

用 GitHub 帳號留言,留言會同步到這個 Blog 的 GitHub Discussions。

閱讀導覽

約 3 分鐘

本篇所在系列 · 第 24 / 24 篇

設計模式

  1. 搞懂設計模式到底是什麼?
  2. 單例模式:只要一個就夠!
  3. 工廠方法模式:點披薩不用親自下廚
  4. 抽象工廠模式:系列產品輕鬆生產
  5. 原型模式:複製的藝術
  6. 建造者模式:一步步完成複雜任務
  7. 介面卡模式:讓不相容也能合作
  8. 橋接模式:抽象與實作分離
  9. 組合模式:樹狀結構的好幫手
  10. 裝飾者模式:讓功能自由加點
  11. 外觀模式:化繁為簡
  12. 享元模式:節省記憶體的利器
  13. 代理模式:控制存取的守門員
  14. 責任鏈模式:層層把關的處理機制
  15. 命令模式:靈活封裝的請求指令
  16. 解譯器模式:讓程式聽懂你的指令
  17. 迭代器模式:輕鬆遍歷集合元素
  18. 中介者模式:管理複雜溝通的好幫手
  19. 備忘錄模式:保存與恢復物件狀態
  20. 觀察者模式:即時通知的好幫手
  21. 狀態模式:依狀態改變行為的祕訣
  22. 策略模式:靈活切換行為的好幫手
  23. 模板方法模式:固定流程靈活實作
  24. 訪問者模式:新增功能不動既有架構
看完整系列 24 篇