訪問者模式是一種行為設計模式,它允許在不改變對象結構的前提下,定義作用于這些對象元素的新操作。
優點:
1.??符合開閉原則:新增操作只需添加新的訪問者類,無需修改現有對象結構。
??2.操作邏輯集中管理??:將相關操作聚合在同一個訪問者中,避免代碼分散。
??3.支持跨對象計算??:通過遍歷對象結構,實現跨元素的全局計算。
??4.增強代碼可讀性??:操作邏輯與數據結構分離,代碼結構更易維護。如渲染、戰斗傷害、AI決策等不同模塊的代碼獨立為不同訪問者。
缺點:
1.破壞對象封裝性?:訪問者需要直接訪問對象內部狀態,強制暴露私有字段或方法。
優化:??1.接口隔離,通過顯式接口限制訪問范圍。
2.元素類型擴展困難:新增元素類型(如新增NPC類)需修改所有訪問者接口和實現。
優化:1.?訪問者適配器模式??:通過中間適配器隔離變化。
3.性能損耗??:頻繁創建訪問者對象導致性能下降。
優化:1.?訪問者對象池??:復用訪問者實例減少GC壓力。2.批處理模式:??合并多次訪問為單次遍歷。3.靜態委托優化??:通過預編譯減少虛方法調用開銷。
4.復雜對象結構支持弱??:對嵌套結構(如樹形結構的場景節點)訪問邏輯復雜。
優化:1.??組合模式集成:??將復雜結構抽象為組合元素。2.訪問者責任鏈:??拆分復雜操作為多個子訪問者鏈式處理:
說明例子:
1.UML類圖:
2.實現:
1.定義圖基類:
public abstract class IGraph{public abstract void Draw(); //繪制public abstract float GetArea(); //獲取面積public abstract int GetVectorCount(); //獲取頂點數public abstract void RunVisitor(IGraphVisitor theVisitor);}
2.定義訪問者基類:
public abstract class IGraphVisitor{//由Cicle類來調用public virtual void VisitCicle(CicleGraph theCicle) { }//由Rectangle類調用public virtual void VisitRectangle(RectangleGraph theRect) { }//由Triangle類調用public virtual void VisitTriangle(TriangleGraph theTriangle) { }}
3.定義容器類:
public class GraphContainer{List<IGraph> m_Graphs = new List<IGraph>();public GraphContainer() { }//新增public void AddShape(IGraph graph){m_Graphs.Add(graph);}//共享的訪問者接口public void RunVisitor(IGraphVisitor theVisitor){foreach (IGraph graph in m_Graphs){graph.RunVisitor(theVisitor);}}}
4.定義具體圖形類:
public class CicleGraph : IGraph{public override void Draw(){Debug.Log("Draw CicleGraph...");}public override int GetVectorCount(){return 9999;}public override float GetArea(){return Mathf.PI * 5 * 5;}public override void RunVisitor(IGraphVisitor theVisitor){theVisitor.VisitCicle(this);}}public class RectangleGraph : IGraph{public override void Draw(){Debug.Log("Draw RectangleGraph...");}public override int GetVectorCount(){return 4;}public override float GetArea(){return 4 * 5;}public override void RunVisitor(IGraphVisitor theVisitor){theVisitor.VisitRectangle(this);}}public class TriangleGraph : IGraph{public override void Draw(){Debug.Log("Draw TriangleGraph...");}public override int GetVectorCount(){return 3;}public override float GetArea(){return .5f * 3 * 5;}public override void RunVisitor(IGraphVisitor theVisitor){theVisitor.VisitTriangle(this);}}
5.定義具體訪問者類:
public class DrawVisitor : IGraphVisitor{public override void VisitCicle(CicleGraph theCicle){theCicle.Draw();}public override void VisiRectangle(RectangleGraph theRect){theRect.Draw();}public override void VisitTriangle(TriangleGraph theTriangle){theTriangle.Draw();}}public class VertexCountVisitor : IGraphVisitor{public int Count = 0;//由Cicle類調用public override void VisitCicle(CicleGraph theCicle){Count = theCicle.GetVectorCount();Debug.Log("VisitCicle Count:" + Count);}//由Rectangle類調用public override void VisitRectangle(RectangleGraph theRect){Count += theRect.GetVectorCount();Debug.Log("VisitRectangle Count:" + Count);}//由Triangle類調用public override void VisitTriangle(TriangleGraph theTriangle){Count += theTriangle.GetVectorCount();Debug.Log("VisitTriangle Count:" + Count);}}public class CicleAreaVisitor : IGraphVisitor{public float Area;//由Sphere類來調用public override void VisitCicle(CicleGraph theCicle){Area += theCicle.GetArea();Debug.Log("VisitCicle Area:" + Area);}}
6.測試:?
public class VisitorPattern : MonoBehaviour{// Start is called before the first frame updatevoid Start(){GraphContainer graphContainer = new GraphContainer();graphContainer.AddShape(new CicleGraph());graphContainer.AddShape(new RectangleGraph());graphContainer.AddShape(new TriangleGraph());graphContainer.RunVisitor(new DrawVisitor());graphContainer.RunVisitor(new VertexCountVisitor());graphContainer.RunVisitor(new CicleAreaVisitor());}}
游戲中使用場景:
1.戰斗系統:??計算不同角色(玩家、敵人)之間的傷害。
??2.存檔系統:??序列化不同類型的游戲對象狀態。
??3.渲染優化:??根據對象類型選擇渲染策略(如LOD、材質替換)。
??4.AI行為決策:??根據場景元素類型生成不同的AI反應。
??5.成就系統?:?檢測特定游戲對象的狀態變化(如擊殺稀有敵人)。
總結:
在游戲開發中,訪客模式特別適合需要跨多種對象類型執行統一邏輯的場景??,如戰斗計算、存檔系統和數據分析模塊。
參考書籍或鏈接:
C# 常用設計模式 (refactoringguru.cn)
《Hands-On Game Development Patterns with Unity 2019》
《設計模式與游戲完美開發》