Golang學習筆記_47——訪問者模式

Golang學習筆記_44——命令模式
Golang學習筆記_45——備忘錄模式
Golang學習筆記_46——狀態模式


文章目錄

    • 一、核心概念
      • 1. 定義
      • 2. 解決的問題
      • 3. 核心角色
      • 4. 類圖
    • 二、特點分析
    • 三、適用場景
      • 1. 編譯器實現
      • 2. 財務系統
      • 3. UI組件系統
    • 四、Go語言實現示例
      • 完整實現代碼
      • 執行結果
    • 五、高級應用
      • 1. 異步訪問者
      • 2. 動態派發優化
    • 六、與其他模式對比
    • 七、實現建議
    • 八、典型應用


一、核心概念

1. 定義

訪問者模式是一種行為型設計模式,允許在不修改已有對象結構的前提下定義新的操作。其核心特點包括:
? 操作解耦:將數據操作與數據結構分離
? 雙重分發:通過兩次方法調用實現動態綁定
? 擴展開放:新增操作無需修改現有類

2. 解決的問題

? 操作污染:頻繁添加新操作導致類不斷膨脹
? 聚合困難:相關操作分散在不同類中
? 類型檢查:避免大量instanceof類型判斷

3. 核心角色

角色作用
Visitor聲明訪問操作的接口(visit方法)
ConcreteVisitor實現具體訪問邏輯
Element定義接受訪問者的接口(accept方法)
ConcreteElement實現accept方法的具體元素
ObjectStructure包含元素集合的容器

4. 類圖

訪問者模式類圖

@startuml
interface Visitor {+ visitElementA(e: ElementA)+ visitElementB(e: ElementB)
}class TaxVisitor {+ visitElementA()+ visitElementB()
}interface Element {+ accept(v: Visitor)
}class ElementA {+ accept(v: Visitor)+ operationA()
}class ElementB {+ accept(v: Visitor)+ operationB()
}Visitor <|.. TaxVisitor
Element <|.. ElementA
Element <|.. ElementB
ElementA ..> Visitor
ElementB ..> Visitornote right of ElementA::accept調用visitor.visitElementA(this)實現雙重分派機制
end note
@enduml

二、特點分析

優點

  1. 擴展性強:新增訪問者不影響現有系統
  2. 職責清晰:相關操作集中管理
  3. 復合操作:支持跨元素的復雜操作

缺點

  1. 破壞封裝:需暴露元素內部細節
  2. 維護困難:元素接口變更影響所有訪問者
  3. 適用局限:適合穩定元素結構的系統

三、適用場景

1. 編譯器實現

type ASTVisitor interface {VisitVariableDecl(n *VariableDecl)VisitFunctionCall(n *FunctionCall)
}type TypeChecker struct{}func (t *TypeChecker) VisitVariableDecl(n *VariableDecl) {fmt.Printf("校驗變量 %s 的類型\n", n.Name)
}

2. 財務系統

type FinancialVisitor interface {VisitInvoice(i *Invoice)VisitPayment(p *Payment)
}type TaxCalculator struct{}func (t *TaxCalculator) VisitInvoice(i *Invoice) {fmt.Printf("計算發票稅款:%.2f\n", i.Amount*0.1)
}

3. UI組件系統

type UIVisitor interface {VisitButton(b *Button)VisitPanel(p *Panel)
}class Renderer struct{}func (r *Renderer) VisitButton(b *Button) {fmt.Printf("渲染按鈕:%s\n", b.Label)
}

四、Go語言實現示例

示例代碼類圖

完整實現代碼

package visitor_demoimport "fmt"// Visitor 接口
type ComputerPartVisitor interface {VisitMouse(m *Mouse)VisitKeyboard(k *Keyboard)
}// Concrete Visitor
type DisplayVisitor struct{}func (d *DisplayVisitor) VisitMouse(m *Mouse) {fmt.Println("顯示鼠標信息:", m.GetSpec())
}func (d *DisplayVisitor) VisitKeyboard(k *Keyboard) {fmt.Println("顯示鍵盤信息:", k.GetLayout())
}// Element 接口
type ComputerPart interface {Accept(visitor ComputerPartVisitor)
}// Concrete Elements
type Mouse struct {dpi int
}func (m *Mouse) Accept(visitor ComputerPartVisitor) {visitor.VisitMouse(m)
}func (m *Mouse) GetSpec() string {return fmt.Sprintf("%d DPI", m.dpi)
}type Keyboard struct {layout string
}func (k *Keyboard) Accept(visitor ComputerPartVisitor) {visitor.VisitKeyboard(k)
}func (k *Keyboard) GetLayout() string {return k.layout
}// Object Structure
type Computer struct {parts []ComputerPart
}func (c *Computer) AddPart(p ComputerPart) {c.parts = append(c.parts, p)
}func (c *Computer) Accept(visitor ComputerPartVisitor) {for _, p := range c.parts {p.Accept(visitor)}
}// 客戶端使用示例
func ExampleUsage() {computer := &Computer{parts: []ComputerPart{&Mouse{dpi: 1600},&Keyboard{layout: "QWERTY"},},}visitor := &DisplayVisitor{}computer.Accept(visitor)
}

執行結果

=== RUN   TestExampleUsage
顯示鼠標信息: 1600 DPI
顯示鍵盤信息: QWERTY
--- PASS: TestExampleUsage (0.00s)
PASS

五、高級應用

1. 異步訪問者

type AsyncVisitor interface {VisitForDB(n Node) <-chan errorVisitForAPI(n Node) <-chan error
}func BatchVisit(nodes []Node, v AsyncVisitor) []error {// 實現并發訪問處理
}

2. 動態派發優化

type DynamicVisitor struct {handlers map[reflect.Type]func(interface{})
}func (dv *DynamicVisitor) Register(t reflect.Type, fn func(interface{})) {dv.handlers[t] = fn
}

六、與其他模式對比

模式核心區別典型應用場景
策略模式單算法選擇 vs 多元素操作支付方式選擇
裝飾器模式增強功能 vs 添加操作IO流處理
組合模式樹形結構 vs 元素遍歷文件系統管理

七、實現建議

  1. 訪問者接口設計
type Visitor interface {VisitTypeA(*TypeA)VisitTypeB(*TypeB)DefaultVisit(interface{})
}
  1. 元素繼承處理
type BaseElement struct{}func (b *BaseElement) Accept(v Visitor) {v.DefaultVisit(b)
}
  1. 循環引用處理
type Element struct {visitor Visitor `json:"-"` // 避免序列化循環
}
  1. 訪問者狀態管理
type StatefulVisitor struct {buffer strings.Builder
}

八、典型應用

  1. 編譯器構建:語法樹檢查/優化
  2. 數據分析:異構數據集合統計
  3. 游戲引擎:場景實體遍歷更新
  4. 文檔處理:多格式導出系統

在Go語言中實現建議:

  • 使用接口組合代替繼承
  • 通過類型斷言實現泛型訪問者
  • 結合通道實現并發訪問
  • 使用sync.Pool優化高頻訪問對象

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71667.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71667.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71667.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

棧概念和結構

文章目錄 1. 棧的概念2. 棧的分類3. 棧的實現&#xff08;數組棧&#xff09;3.1 接口設計&#xff08;Stack.h&#xff09;3.2 接口實現&#xff08;Stack.c&#xff09;1&#xff09;初始化銷毀2&#xff09;棧頂插入刪除3&#xff09;棧頂元素、空棧、大小 3.3 完整代碼Stac…

GitCode 助力 vue3-element-admin:開啟中后臺管理前端開發新征程

源碼倉庫&#xff1a; https://gitcode.com/youlai/vue3-element-admin 后端倉庫&#xff1a; https://gitcode.com/youlai/youlai-boot 開源助力&#xff0c;開啟中后臺快速開發之旅 vue3-element-admin 是一款精心打造的免費開源中后臺管理前端模板&#xff0c;它緊密貼合…

算法.習題篇

算法 — 地大復試 模擬 while循環和MOD循環計數 1.約瑟夫問題 http://bailian.openjudge.cn/practice/3254 using namespace std;bool isNoPeople(vector<bool> c)//判斷當前數組是否一個小孩都沒有了 {bool nopeople true;for (bool ival : c){if ( ival true)nop…

大白話JavaScript實現一個函數,將字符串中的每個單詞首字母大寫。

大白話JavaScript實現一個函數&#xff0c;將字符串中的每個單詞首字母大寫。 答題思路 理解需求&#xff1a;要寫一個函數&#xff0c;它能接收一個字符串&#xff0c;然后把這個字符串里每個單詞的第一個字母變成大寫。分解步驟 拆分單詞&#xff1a;一般單詞之間是用空格隔…

react中如何使用使用react-redux進行數據管理

以上就是react-redux的使用過程&#xff0c;下面我們開始優化部分&#xff1a;當一個組件只有一個render生命周期&#xff0c;那么我們可以改寫成一個無狀態組件&#xff08;UI組件到無狀態組件&#xff0c;性能提升更好&#xff09;

廣告營銷,會被AI重構嗎?

DeepSeek設計&#xff0c;即夢AI繪圖&#xff0c;剪映成片。 DeepSeek的熱度還在高開瘋走。 用戶對于各個場景下DS應用的探索也還在持續&#xff0c;各種DS的模式被挖掘出來&#xff0c;超級個體們開始給手下的大模型團隊進行分工&#xff0c;實踐出各種場景下最佳的排列組合方…

國產編輯器EverEdit - 宏功能介紹

1 宏 1.1 應用場景 宏是一種重復執行簡單工作的利器&#xff0c;可以讓用戶愉快的從繁瑣的工作中解放出來&#xff0c;其本質是對鍵盤和菜單的操作序列的錄制&#xff0c;并不會識別文件的內容&#xff0c;屬于無差別無腦執行。 特別是對一些有規律的重復按鍵動作&#xff0c;…

vscode離線配置遠程服務器

目錄 一、前提 二、方法 2.1 查看vscode的commit_id 2.2 下載linux服務器安裝包 2.3 安裝包上傳到遠程服務器&#xff0c;并進行文件解壓縮 三、常見錯誤 Failed to set up socket for dynamic port forward to remote port&#xff08;vscode報錯解決方法&#xff09;-C…

OmniDrive(1): 論文解讀

多模態大語言模型(MLLMs)的發展推動了基于 LLM 的自動駕駛研究,以利用其強大的推理能力。然而,利用多模態大語言模型(MLLMs)強大的推理能力來改進planning具有挑戰性,因為這需要超越二維推理的完整三維情境感知能力。因為這不單單需要 2D 推理還需要完整的 3D 場景感知能…

ubuntu22.04安裝RAGFlow配合DeepSeek搭建本地知識庫

一、簡介 RAGFlow 是一個基于對文檔的深入理解的開源 RAG&#xff08;檢索增強生成&#xff09;引擎。當與 LLM 集成時&#xff0c;它能夠提供真實的問答功能&#xff0c;并以來自各種復雜格式數據的有根據的引用為后盾。 二、安裝 1.環境要求 CPU ≥ 4 核 &#xff08;x86…

Android AudioFlinger(四)—— 揭開PlaybackThread面紗

前言&#xff1a; 繼上一篇Android AudioFlinger&#xff08;三&#xff09;—— AndroidAudio Flinger 之設備管理我們知道PlaybackThread繼承自Re’fBase&#xff0c; 在被第一次引用的時候就會調用onFirstRef&#xff0c;實現如下&#xff1a; void AudioFlinger::Playbac…

個人電腦本地部署DeepSeek來離線使用

文章目錄 前言軟件下載DeepSeek部署ChatBox集成 前言 最近這段時間&#xff0c;“DeepSeek”&#xff08;深度求索&#xff09;人工智能平臺非常的火爆&#xff0c;正確的使用可以幫我們做很多很多事情&#xff0c;通常我們是在瀏覽器網頁或手機APP使用&#xff0c;但是有時會…

第一:goland安裝

GOPROXY (會話臨時性)&#xff0c;長久的可以在配置文件中配置 go env -w GOPROXYhttps://goproxy.cn,direct 長久的&#xff0c;在~/.bashrc文件中添加&#xff1a; export GOPROXYhttps://goproxy.cn,direct &#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d…

介紹一下Qt中的事件過濾

在 Qt 中&#xff0c;事件過濾&#xff08;Event Filter&#xff09;是一種強大的機制&#xff0c;它允許一個對象攔截并處理另一個對象接收到的事件。通過事件過濾&#xff0c;可以在事件到達目標對象之前對其進行監控和修改&#xff0c;這在很多場景下都非常有用&#xff0c;…

Go紅隊開發—格式導出

文章目錄 輸出功能CSV輸出CSV 轉 結構體結構體 轉 CSV端口掃描結果使用CSV格式導出 HTML輸出Sqlite輸出nmap掃描 JSONmap轉json結構體轉jsonjson寫入文件json編解碼json轉結構體json轉mapjson轉string練習&#xff1a;nmap掃描結果導出json格式 輸出功能 在我們使用安全工具的…

SwanLab簡明教程:從萌新到高手

目錄 1. 什么是SwanLab&#xff1f; 1.1 核心特性 2. 安裝SwanLab 3. 登錄SwanLab賬號&#xff08;云端版&#xff09; 4. 5分鐘快速上手 更多案例 5. SwanLab功能組件 5.1 圖表視圖 5.2 表格視圖 5.3 硬件監控 5.4 環境記錄 5.5 組織協同 6. 訓練框架集成 6.1 基…

2025天梯訓練1

PTA | L3-1 直搗黃龍 30分 思路&#xff1a;多關鍵字最短路&#xff0c;同時還要記錄最短路徑條數。 typedef struct node{int from,d,pass,kl;bool operator<(const node &x)const{if(d!x.d) return d>x.d;if(pass!x.pass) return pass<x.pass;return kl<x.…

EasyRTC嵌入式視頻通話SDK的跨平臺適配,構建web瀏覽器、Linux、ARM、安卓等終端的低延遲音視頻通信

1、技術背景 WebRTC是一項開源項目&#xff0c;旨在通過簡單的API為瀏覽器和移動應用程序提供實時通信&#xff08;RTC&#xff09;功能。它允許在無需安裝插件或軟件的情況下&#xff0c;實現點對點的音頻、視頻和數據傳輸。 WebRTC由三個核心組件構成&#xff1a; GetUserM…

【git】ssh配置提交 gitcode-ssh提交

【git】ssh配置提交 gitcode-ssh提交 之前一直用的是gitee和阿里云的倉庫&#xff0c;前兩天想在gitcode上面備份一下我的打洞代碼和一些資料 就直接使用http克隆了下來 。 在提交的時候他一直會讓我輸入賬號和密碼&#xff0c;但是我之前根本沒有設置過這個&#xff0c;根本沒…

Dify部署踩坑指南(Windows+Mac)

組件說明 Dify踩坑及解決方案 ?? 除了修改鏡像版本&#xff0c;nginx端口不要直接修改docker-compose.yaml &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 1、更換鏡像版本 這個文件是由.env自動生成的&#xff0c;在.env配置 …