linux檔案共享
阿新 • • 發佈:2021-11-22
概述
表示一個作用於某物件結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作
允許一個或者多個操作應用到一組物件上,解耦操作和物件本身
但為了避免不斷新增功能導致類不斷膨脹,職責越來越不單一,以及避免頻繁地新增功能導致的頻繁程式碼修改,我們使用訪問者模式,將物件與操作解耦,將這些業務操作抽離出來,定義在獨立細分的訪問者類
結構圖
程式碼實現
元素
/// <summary> /// 抽象元素 /// </summary> public abstract class Element {public abstract void Accept(Visitor visitor); }
/// <summary> /// 具體元素A /// </summary> public class ConcreteElementA : Element { public override void Accept(Visitor visitor) { visitor.VisitConcreteElementA(this); } public void OperationA() { } }
/// <summary> /// 具體元素B /// </summary> public class ConcreteElementB : Element { public override void Accept(Visitor visitor) { visitor.VisitConcreteElementB(this); } public void OperationB() { } }
訪問者
/// <summary>/// 抽象訪問者 /// </summary> public abstract class Visitor { public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA); public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB); }
/// <summary> /// 具體訪問者1 /// </summary> public class ConcreteVisitor1 : Visitor { public override void VisitConcreteElementA(ConcreteElementA concreteElementA) { Console.WriteLine("{0}被{1}訪問", concreteElementA.GetType().Name, this.GetType().Name); } public override void VisitConcreteElementB(ConcreteElementB concreteElementB) { Console.WriteLine("{0}被{1}訪問", concreteElementB.GetType().Name, this.GetType().Name); } }
/// <summary> /// 具體訪問者2 /// </summary> public class ConcreteVisitor2 : Visitor { public override void VisitConcreteElementA(ConcreteElementA concreteElementA) { Console.WriteLine("{0}被{1}訪問", concreteElementA.GetType().Name, this.GetType().Name); } public override void VisitConcreteElementB(ConcreteElementB concreteElementB) { Console.WriteLine("{0}被{1}訪問", concreteElementB.GetType().Name, this.GetType().Name); } }
物件結構
/// <summary> /// 物件結構 /// </summary> public class ObjectStructure { private IList<Element> elements = new List<Element>(); public void Attach(Element element) { elements.Add(element); } public void Detach(Element element) { elements.Remove(element); } public void Accept(Visitor visitor) { foreach (Element e in elements) { e.Accept(visitor); } } }
客戶端
class Program { static void Main(string[] args) { ObjectStructure o = new ObjectStructure(); o.Attach(new ConcreteElementA()); o.Attach(new ConcreteElementB()); ConcreteVisitor1 v1 = new ConcreteVisitor1(); ConcreteVisitor2 v2 = new ConcreteVisitor2(); o.Accept(v1); o.Accept(v2); Console.Read(); } }
執行結果
優勢
擴充套件性好。能夠在不修改物件結構中的元素的情況下,為物件結構中的元素新增新的功能。
複用性好。可以通過訪問者來定義整個物件結構通用的功能,從而提高系統的複用程度。
靈活性好。訪問者模式將資料結構與作用於結構上的操作解耦,使得操作集合可相對自由地演化而不影響系統的資料結構。
符合單一職責原則。訪問者模式把相關的行為封裝在一起,構成一個訪問者,使每一個訪問者的功能都比較單一。
使用場景
穩定的資料結構和易變的操作耦合問題。
需要對一個物件結構中的物件進行很多不同的並且不相關的操作,而需要避免讓這些操作"汙染"這些物件的類,使用訪問者模式將這些封裝到類中。
物件結構相對穩定,但其操作演算法經常變化的程式。
物件結構中的物件需要提供多種不同且不相關的操作,而且要避免讓這些操作的變化影響物件的結構。
物件結構包含很多型別的物件,希望對這些物件實施一些依賴於其具體型別的操作。
缺陷
具體元素對訪問者公佈細節,違反了迪米特原則。
具體元素變更比較困難。
違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。