Analogia z życia:
Ludzie mieszkają w mieszkaniach, które zazwyczaj są zamykane przed innymi ludźmi. Czasami zdarzają się jednak sytuacje, gdy ktoś obcy musi wejść do naszego mieszkania, np. żeby naprawić kran. Wtedy otwieramy mieszkanie dla takiej osoby, udostępniamy mu wybraną jego część (kuchnię) i pozwolimy, by wykonał odpowiednie czynności.
Zastosowanie:
Wszędzie tam, gdzie chcemy wydzielić jakąś operację, wykonywaną na obiekcie danego typu poza definicję tego typu. Jeżeli obiekt dobrze implementuje enkapsulację, to nikt z zewnątrz nie może dostać się do jego stanu, a jednocześnie operacje na tym stanie może wykonywać specjalny typ - visitor.
Zasada działania:
Definiuje się dwie rodziny obiektów (rodziny rozumiane jako klasa bazowa plus jej implementacje), elementy oraz wizytorzy. Element to obiekt zawierający strukturę danych i udostępniający operację Visit przyjmującą jako parametr obiekt z rodziny wizytorów. Visitor i elementy po nim dziedziczące reprezentują akcje wykonywane na obiektach typu Element. Visitor wystawia metodę Accept przyjmującą elementy dziedziczące po klasie Element i wykonujące na niej dane operacje.
Definicja grupy elementów:
public abstract class Element { public abstract void Accept(Visitor visitor); } public class Tap : Element { public override void Accept(Visitor visitor) { visitor.VisitKitchen(this); } } public class Shower : Element { public override void Accept(Visitor visitor) { visitor.VisitBathroom(this); } }
Definicja wizytatora:
public abstract class Visitor { public abstract void VisitKitchen(Tap tap); public abstract void VisitBathroom(Shower shower); } public class Plumber : Visitor { public override void VisitBathroom(Shower shower) { Console.WriteLine("Repairing " + nameof(shower)); } public override void VisitKitchen(Tap tap) { Console.WriteLine("Repairing " + nameof(tap)); } }
Definicja obiektu mieszkania, akceptującego "wizytę":
public class Flat { private List<Element> _stuff = new List<Element>(); public void Attach(Element element) { _stuff.Add(element); } public void Detach(Element element) { _stuff.Remove(element); } public void Accept(Visitor visitor) { foreach (Element element in _stuff) { element.Accept(visitor); } } }
static void Main(string[] args) { var flat = new Flat(); flat.Attach(new Tap()); flat.Attach(new Shower()); flat.Accept(new Plumber()); Console.ReadKey(); }