訪問者模式(Vistor):
訪問者模式的官方定義是這樣的:表示一個作用于某物件結構中的各元素的操作,它使你可以在不改變各元素類的前提下定義作用于這些元素的新操作,官方的東西總是晦澀難懂的,那么我們現在就來拆解一下:首先"一個作用于某物件結構中的各元素的操作",提到了三個東西:物件結構、元素、操作,我們都學習過資料結構,資料結構中大家對資料的訪問一般都是直接訪問其地址,在面向物件的設計中,我們一般也是將資料的訪問操作放在類的內部,便于訪問,這種設計看似沒有什么問題,但當我們想要采用不同方式訪問資料或物件結構時就必須要對類進行修改,這樣就違反了OCP原則,于是大家會想到將資料結構與操作分離開來,當問們需要添加訪問操作的時候直接添加新的類,原來的代碼不需要做任何改變,這也是后半句提到的"可以在不改變各元素類的前提下定義作用于這些元素的新操作",
訪問者模式的角色:

1)Visitor:介面或抽象類,定義了對每個Element訪問的行為,它的引數就是被訪問的元素,它的方法個數理論上與元素的個數是一樣的,因此,訪問者模式要求元素的型別要穩定,如果經常添加、移除元素類,必然會導致頻繁地修改visitor介面,如果出現這種情況,則說明不適合使用該模式,
2)ConcreteVisitor:具體的訪問者,它需要給出對每一個元素類訪問時所產生的具體行為,
3)Element:元素介面或抽象類,它定義了一個接受訪問者的方法(accept),其意思就是說每一個元素都可以被訪問者訪問,
4)ConcreteElement:具體的元素類,它提供接受訪問的具體實作,而這個具體實作通常情況下是使用訪問者提供的訪問該元素類的方法,
5)ObjectStructure:定義當中所提到的物件結構,物件結構是一個抽象表述,它內部管理了元素集合,并且可以迭代這些元素提供訪問者訪問,
示例:
一個目錄下面有檔案夾和檔案,檔案夾和檔案是具體的元素類,
1 /// <summary> 2 /// 抽象訪問者 3 /// </summary> 4 public abstract class Visitor 5 { 6 public abstract void visit(File file); 7 8 public abstract void visit(Directory directory); 9 }10 11 /// <summary>12 /// 具體的訪問者13 /// </summary>14 public class ListVisitor : Visitor15 {16 public override void visit(File file)17 {18 Console.WriteLine($"檔案名稱{file.GetName()}");19 }20 21 public override void visit(Directory directory)22 {23 Console.WriteLine($"檔案夾名稱{directory.GetName()}");24 }25 }26 27 /// <summary>28 /// 元素抽象類29 /// </summary>30 public abstract class Element31 {32 public abstract void accept(Visitor visitor);33 }34 35 public class Entry : Element36 {37 private string name;38 39 public Entry(string name)40 {41 this.name = name;42 }43 44 public string GetName()45 {46 return this.name;47 }48 49 public override void accept(Visitor visitor)50 {51 throw new NotImplementedException();52 }53 }54 55 /// <summary>56 /// 具體的元素類:檔案夾57 /// </summary>58 public class Directory : Entry59 {60 public Directory(string name)61 : base(name)62 {63 }64 65 public override void accept(Visitor visitor)66 {67 visitor.visit(this);68 }69 }70 71 /// <summary>72 /// 具體的元素類:檔案73 /// </summary>74 public class File : Entry75 {76 public File(string name)77 : base(name)78 {79 }80 81 public override void accept(Visitor visitor)82 {83 visitor.visit(this);84 }85 }
定義好了,資料操作,接下來我們定義資料結構的核心類ObjectStructure,
1 public class ObjectStructure 2 { 3 private readonly Visitor visitor; 4 private List<Element> list = new List<Element>(); 5 6 public ObjectStructure(Visitor visitor) 7 { 8 this.visitor = visitor; 9 }10 11 public void Add(Element element)12 {13 list.Add(element);14 }15 16 public void Show()17 {18 foreach (Element element in list)19 {20 element.accept(visitor);21 }22 }23 }
客戶端呼叫,
1 private static void Main(string[] args) 2 { 3 ObjectStructure objectStructure = new ObjectStructure(new ListVisitor()); 4 objectStructure.Add(new Directory("我的檔案夾")); 5 objectStructure.Add(new File("C#高級編程.pdf")); 6 objectStructure.Add(new File("設計模式.pdf")); 7 objectStructure.Add(new File("演算法.txt")); 8 objectStructure.Add(new File("mm.png")); 9 objectStructure.Show();10 }
訪問者模式的優缺點:
優點:
1)各角色職責分離,符合單一職責原則,
2)具有優秀的擴展性,使得資料結構和作用于結構上的操作解耦,使得操作集合可以獨立變化,
3)靈活性
缺點:
1)具體元素對訪問者公布細節,違反了迪米特原則,
2)具體元素變更比較困難,
3)違反了依賴倒置原則,依賴了具體類,沒有依賴抽象,
訪問者模式的使用場景:
1)物件結構中物件對應的類很少改變,但經常需要在此物件結構上定義新的操作,
2)需要對一個物件結構中的物件進行很多不同的并且不相關的操作,而需要避免讓這些操作"污染"這些物件的類,也不希望在增加新操作時修改這些類,
參考:https://www.cnblogs.com/zyrblog/p/9244754.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/39932.html
標籤:設計模式
上一篇:部分設計模式對比分析
