【行為型之訪問者模式】游戲開發實戰——Unity靈活數據操作與跨系統交互的架構秘訣

文章目錄

      • 🧳 訪問者模式(Visitor Pattern)深度解析
        • 一、模式本質與核心價值
        • 二、經典UML結構
        • 三、Unity實戰代碼(游戲物品系統)
          • 1. 定義元素與訪問者接口
          • 2. 實現具體元素類
          • 3. 實現具體訪問者
          • 4. 對象結構管理
          • 5. 客戶端使用
        • 四、模式進階技巧
          • 1. 動態訪問者注冊
          • 2. 訪問者組合模式
          • 3. 異步訪問處理
        • 五、游戲開發典型應用場景
        • 六、性能優化策略
        • 七、模式對比與選擇
        • 八、最佳實踐原則
        • 九、常見問題解決方案

🧳 訪問者模式(Visitor Pattern)深度解析

——以Unity實現靈活數據操作跨系統交互為核心案例


一、模式本質與核心價值

核心目標
? 分離數據結構與數據操作,支持在不修改元素類的前提下定義新操作
? 集中相關操作,避免污染元素類代碼
? 實現雙重分派,動態選擇元素處理方法

關鍵術語

  • Visitor(訪問者接口):聲明訪問各類元素的接口
  • ConcreteVisitor(具體訪問者):實現特定操作的訪問邏輯
  • Element(元素接口):定義接受訪問者的方法
  • ObjectStructure(對象結構):維護元素集合,提供遍歷接口

數學表達
設元素集合E = {e?, e?, …, e?},訪問者V,則操作執行過程為:
?e ∈ E, e.Accept(V) → V.Visit(e)


二、經典UML結構
accept
accept
?interface?
IVisitor
+VisitWeapon(Weapon)
+VisitPotion(Potion)
DamageCalculator
+VisitWeapon()
+VisitPotion()
?interface?
IItem
+Accept(IVisitor)
Weapon
+Accept()
Potion
+Accept()

三、Unity實戰代碼(游戲物品系統)
1. 定義元素與訪問者接口
public interface IItem {void Accept(IItemVisitor visitor);
}public interface IItemVisitor {void Visit(Weapon weapon);void Visit(Potion potion);void Visit(QuestItem questItem);
}
2. 實現具體元素類
public class Weapon : MonoBehaviour, IItem {public int Damage;public string ElementType;public void Accept(IItemVisitor visitor) {visitor.Visit(this);}
}public class Potion : MonoBehaviour, IItem {public float HealAmount;public int Charges;public void Accept(IItemVisitor visitor) {visitor.Visit(this);}
}
3. 實現具體訪問者
// 傷害計算訪問者
public class DamageCalculator : IItemVisitor {private float _totalDamage;public void Visit(Weapon weapon) {_totalDamage += weapon.Damage * (weapon.ElementType == "Fire" ? 1.2f : 1f);}public void Visit(Potion potion) {// 藥水不貢獻傷害}public void Visit(QuestItem questItem) {// 任務物品不貢獻傷害}public float GetTotalDamage() => _totalDamage;
}// 存檔序列化訪問者
public class SaveVisitor : IItemVisitor {private List<byte[]> _serializedData = new();public void Visit(Weapon weapon) {var data = Encoding.UTF8.GetBytes($"Weapon|{weapon.Damage}|{weapon.ElementType}");_serializedData.Add(data);}public void Visit(Potion potion) {var data = Encoding.UTF8.GetBytes($"Potion|{potion.HealAmount}|{potion.Charges}");_serializedData.Add(data);}public byte[] GetSaveData() {return _serializedData.SelectMany(arr => arr).ToArray();}
}
4. 對象結構管理
public class InventorySystem : MonoBehaviour {private List<IItem> _items = new();public void AddItem(IItem item) => _items.Add(item);public void ProcessItems(IItemVisitor visitor) {foreach(var item in _items) {item.Accept(visitor);}}
}
5. 客戶端使用
public class GameManager : MonoBehaviour {[SerializeField] private InventorySystem _inventory;void Start() {// 計算總傷害var damageCalc = new DamageCalculator();_inventory.ProcessItems(damageCalc);Debug.Log($"總傷害值:{damageCalc.GetTotalDamage()}");// 生成存檔數據var saver = new SaveVisitor();_inventory.ProcessItems(saver);SaveToFile(saver.GetSaveData());}
}

四、模式進階技巧
1. 動態訪問者注冊
public class DynamicVisitor : IItemVisitor {private Dictionary<Type, Action<object>> _handlers = new();public void RegisterHandler<T>(Action<T> handler) where T : IItem {_handlers[typeof(T)] = obj => handler((T)obj);}public void Visit(Weapon weapon) => InvokeHandler(weapon);public void Visit(Potion potion) => InvokeHandler(potion);private void InvokeHandler<T>(T item) where T : IItem {if(_handlers.TryGetValue(typeof(T), out var handler)) {handler(item);}}
}
2. 訪問者組合模式
public class CompositeVisitor : IItemVisitor {private List<IItemVisitor> _visitors = new();public void AddVisitor(IItemVisitor visitor) => _visitors.Add(visitor);public void Visit(Weapon weapon) {foreach(var v in _visitors) v.Visit(weapon);}public void Visit(Potion potion) {foreach(var v in _visitors) v.Visit(potion);}
}
3. 異步訪問處理
public class AsyncVisitor : MonoBehaviour, IItemVisitor {public async Task ProcessAsync(InventorySystem inventory) {var tasks = new List<Task>();foreach(var item in inventory.Items) {tasks.Add(Task.Run(() => item.Accept(this)));}await Task.WhenAll(tasks);}public void Visit(Weapon weapon) {// 異步處理武器}
}

五、游戲開發典型應用場景
  1. 成就系統觸發

    public class AchievementVisitor : IItemVisitor {public void Visit(Weapon w) {if(w.Damage > 100) Unlock("POWER_WEAPON");}
    }
    
  2. 戰斗傷害計算

    public class BattleDamageVisitor : IItemVisitor {private float _totalDamage;public void Visit(Weapon w) {_totalDamage += CalculateElementDamage(w);}
    }
    
  3. 場景序列化存檔

    public class SceneSaveVisitor : IItemVisitor {private List<SerializableData> _sceneData = new();public void Visit(Enemy e) {_sceneData.Add(new EnemyData(e.Position, e.Health));}
    }
    
  4. UI數據綁定

    public class UIDataVisitor : IItemVisitor {public void Visit(Weapon w) {InventoryUI.UpdateWeaponSlot(w);}
    }
    

六、性能優化策略
策略實現方式適用場景
訪問緩存緩存頻繁訪問結果復雜計算場景
批處理合并多個訪問操作大量元素遍歷
并行處理使用Job System并行訪問CPU密集型操作
惰性求值延遲執行非關鍵訪問性能敏感場景

七、模式對比與選擇
維度訪問者模式策略模式
關注點跨類操作算法替換
擴展方向新增操作新增算法
元素穩定性元素類需穩定策略可任意擴展
典型應用數據序列化戰斗計算

八、最佳實踐原則
  1. 元素接口穩定:避免頻繁修改元素類接口
  2. 訪問者單一職責:每個訪問者專注一個功能領域
  3. 防御性訪問:處理未知元素類型
    public class SafeVisitor : IItemVisitor {public void Visit(IItem item) {if(item is Weapon w) VisitWeapon(w);else Debug.LogWarning($"未知物品類型:{item.GetType()}");}
    }
    
  4. 訪問順序控制
    public void ProcessItems(IItemVisitor visitor) {// 按優先級排序處理foreach(var item in _items.OrderBy(i => i.Priority)) {item.Accept(visitor);}
    }
    

九、常見問題解決方案

Q1:如何處理新增元素類型?
→ 使用反射擴展訪問者

public class ReflectionVisitor {private Dictionary<Type, MethodInfo> _methods = new();public void Visit(IItem item) {var type = item.GetType();if(_methods.TryGetValue(type, out var method)) {method.Invoke(this, new[]{item});}}
}

Q2:如何避免循環依賴?
→ 引入中間接口層

public interface IWeaponVisitor {void VisitWeapon(Weapon weapon);
}public class DamageCalculator : IItemVisitor, IWeaponVisitor {public void Visit(Weapon w) => VisitWeapon(w);public void VisitWeapon(Weapon w) { /* 具體邏輯 */ }
}

Q3:如何調試復雜訪問流程?
→ 實現訪問日志代理

public class LoggingVisitorProxy : IItemVisitor {private IItemVisitor _wrapped;public void Visit(Weapon w) {Debug.Log($"開始處理武器:{w.Name}");_wrapped.Visit(w);Debug.Log("武器處理完成");}
}

上一篇 【行為型之模板方法模式】游戲開發實戰——Unity標準化流程與可擴展架構的核心實現

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

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

相關文章

SQL:MySQL函數:日期函數(Date Functions)

目錄 時間是數據的一種類型 &#x1f9f0; MySQL 常用時間函數大全 &#x1f7e6; 1. 獲取當前時間/日期 &#x1f7e6; 2. 日期運算&#xff08;加減&#xff09; &#x1f7e6; 3. 時間差計算 &#x1f7e6; 4. 格式化日期 &#x1f7e6; 5. 提取時間部分 &#x1f7…

【MySQL】數據表更新數據

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;MySQL 文章目錄 1. 數據更新基礎1.1 更新操作的重要性1.2 更新語句基本結構1.3 更新操作注意事項 2. 基本更新操作2.1 基本UPDATE語法2.2 使用表達式更新數據2.3 使用LIMIT限制更新行數2.4 NULL值處理 3. 高級更新技術3.1 使用子…

【更新】全國省市縣-公開手機基站數據集(2006-2025.3)

手機基站是現代通信網絡中的重要組成部分&#xff0c;它們為廣泛的通信服務提供基礎設施。隨著數字化進程的不斷推進&#xff0c;手機基站的建設與布局對優化網絡質量和提升通信服務水平起著至關重要的作用&#xff0c;本分享數據可幫助分析移動通信網絡的發展和優化。本次數據…

藍橋杯12屆國B 純質數

題目描述 如果一個正整數只有 1 和它本身兩個約數&#xff0c;則稱為一個質數&#xff08;又稱素數&#xff09;。 前幾個質數是&#xff1a;2,3,5,7,11,13,17,19,23,29,31,37,??? 。 如果一個質數的所有十進制數位都是質數&#xff0c;我們稱它為純質數。例如&#xff1…

騰訊多模態定制化視頻生成框架:HunyuanCustom

HunyuanCustom 速讀 一、引言 HunyuanCustom 是由騰訊團隊提出的一款多模態定制化視頻生成框架。該框架旨在解決現有視頻生成方法在身份一致性(identity consistency)和輸入模態有限性方面的不足。通過支持圖像、音頻、視頻和文本等多種條件輸入&#xff0c;HunyuanCustom 能…

力扣top100 矩陣置零

開辟數組來標記元素為0的行和列&#xff0c;然后將對應的行和列的元素全部置為0&#xff1b; class Solution { public:void setZeroes(vector<vector<int>>& matrix) {int n matrix.size();int m matrix[0].size();vector<int> l(m),r(n);for(int i …

Python知識框架

一、Python基礎語法 變量與數據類型 變量命名規則 基本類型&#xff1a;int, float, str, bool, None 復合類型&#xff1a;list, tuple, dict, set 類型轉換與檢查&#xff08;type(), isinstance()&#xff09; 運算符 算術運算符&#xff1a;, -, *, /, //, %, ** 比較…

華為OD機試真題——單詞接龍(首字母接龍)(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳實現

2025 A卷 100分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分…

微信小程序智能商城系統(uniapp+Springboot后端+vue管理端)

一、系統介紹 本智能商城系統是基于當今主流技術棧開發的一款多端商城解決方案&#xff0c;主要包括微信小程序前端、SpringBoot 后端服務以及 Vue 管理后臺三大部分。系統融合了線上商城的核心功能&#xff0c;支持商品瀏覽、下單、支付、訂單管理等操作&#xff0c;適用于中小…

Python筆記:c++內嵌python,c++主窗口如何傳遞給腳本中的QDialog,使用的是pybind11

1. 問題描述 用的是python 3.8.20, qt版本使用的是5.15.2, PySide的版本是5.15.2, pybind11的版本為2.13.6 網上說在python腳本中直接用PySide2自帶的QWinWidget&#xff0c;如from PySide2.QtWinExtras import QWinWidget&#xff0c;但我用的版本中說沒有QWinWidget&#x…

軟考軟件設計師中級——軟件工程筆記

1.軟件過程 1.1能力成熟度模型&#xff08;CMM&#xff09; 軟件能力成熟度模型&#xff08;CMM&#xff09;將軟件過程改進分為以下五個成熟度級別&#xff0c;每個級別都定義了特定的過程特征和目標&#xff1a; 初始級 (Initial)&#xff1a; 軟件開發過程雜亂無章&#xf…

C# SQLite基本使用示例

目錄 1 基本使用流程 1.1 步驟1&#xff1a;添加SQLite依賴 1.2 ?步驟2&#xff1a;建立連接 1.3 步驟3&#xff1a;執行SQL命令 1.4 步驟4&#xff1a;查詢數據 1.5 步驟5&#xff1a;使用事務 2 SQLite基本使用示例 2.1 準備工作 2.2 完整示例 2.3 案例代碼解析 …

視頻圖像壓縮領域中 DCT 的 DC 系數和 AC 系數詳解

引言 在數字圖像與視頻壓縮領域&#xff0c;離散余弦變換&#xff08;Discrete Cosine Transform, DCT&#xff09;憑借其卓越的能量集中特性&#xff0c;成為JPEG、MPEG等國際標準的核心技術。DCT通過將空域信號映射到頻域&#xff0c;分離出DC系數&#xff08;直流分量&…

對抗系統熵增:從被動救火到主動防御的穩定性實戰

&#x1f4d5;我是廖志偉&#xff0c;一名Java開發工程師、《Java項目實戰——深入理解大型互聯網企業通用技術》&#xff08;基礎篇&#xff09;、&#xff08;進階篇&#xff09;、&#xff08;架構篇&#xff09;清華大學出版社簽約作家、Java領域優質創作者、CSDN博客專家、…

java 中 DTO 和 VO 的核心區別

DTO 和 VO 的核心區別 特性DTO&#xff08;數據傳輸對象&#xff09;VO&#xff08;視圖對象&#xff09;設計目的服務層與外部系統&#xff08;如前端、其他服務&#xff09;之間的數據傳輸為前端展示層定制數據&#xff0c;通常與 UI 強綁定數據內容可能包含業務邏輯需要的字…

數據結構【二叉樹的遍歷實現】

&#x1f4d8;考研數據結構基礎&#xff1a;二叉樹的存儲、遍歷與隊列輔助實現詳 在數據結構的學習中&#xff0c;二叉樹作為一種結構清晰、應用廣泛的樹形結構&#xff0c;是考研計算機專業課中重點內容之一。本文將以實際代碼為基礎&#xff0c;介紹二叉樹的存儲結構、遍歷方…

無人機俯視風光攝影Lr調色預設,手機濾鏡PS+Lightroom預設下載!

調色詳情 無人機俯視風光攝影 Lr 調色是利用 Adobe Lightroom 軟件&#xff0c;對無人機從俯視角度拍攝的風光照片進行后期處理的調色方式。通過調整色彩、對比度、光影等多種參數&#xff0c;能夠充分挖掘并強化畫面獨特視角下的壯美與細節之美&#xff0c;讓原本平凡的航拍風…

【springcloud學習(dalston.sr1)】Eureka服務端集群的搭建(含源代碼)(二)

該系列項目整體介紹及源代碼請參照前面寫的一篇文章【springcloud學習(dalston.sr1)】項目整體介紹&#xff08;含源代碼&#xff09;&#xff08;一&#xff09; 這篇文章主要介紹多個eureka服務端的集群環境是如何搭建的。 &#xff08;一&#xff09;eureka的簡要說明 Eu…

互聯網大廠Java求職面試實戰:Spring Boot微服務與數據庫優化詳解

&#x1f4aa;&#x1f3fb; 1. Python基礎專欄&#xff0c;基礎知識一網打盡&#xff0c;9.9元買不了吃虧&#xff0c;買不了上當。 Python從入門到精通 &#x1f601; 2. 畢業設計專欄&#xff0c;畢業季咱們不慌忙&#xff0c;幾百款畢業設計等你選。 ?? 3. Python爬蟲專欄…

事件驅動reactor的原理與實現

fdset 集合&#xff1a;&#xff08;就是說&#xff09; fd_set是一個位圖&#xff08;bitmap&#xff09;結構 每個位代表一個文件描述符 0表示不在集合中&#xff0c;1表示在集合中 fd_set結構&#xff08;簡化&#xff09;&#xff1a; [0][1][2][3][4][5]...[1023] …