diff --git a/Program.cs b/Program.cs index b09cc41..6377c63 100644 --- a/Program.cs +++ b/Program.cs @@ -23,6 +23,7 @@ using design_patterns.behavioral.observer; using design_patterns.behavioral.state; using design_patterns.behavioral.strategy; using design_patterns.behavioral.template; +using design_patterns.behavioral.visitor; namespace design_patterns { @@ -59,7 +60,8 @@ namespace design_patterns // await ObserverSample.Run(); // await StateSample.Run(); // await StrategySample.Run(); - await TemplateSample.Run(); + // await TemplateSample.Run(); + await VisitorSample.Run(); } catch (System.Exception ex) { diff --git a/behavioral/visitor/VisitorSample.cs b/behavioral/visitor/VisitorSample.cs new file mode 100644 index 0000000..2ff6083 --- /dev/null +++ b/behavioral/visitor/VisitorSample.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace design_patterns.behavioral.visitor +{ + /// + /// Visitor is a behavioral design pattern that lets you + /// separate algorithms from the objects on which they operate. + /// + /// Use it when: + /// - you need to perform an operation on all elements of a + /// complex object structure (for example, an object tree). + /// - to clean up the business logic of auxiliary behaviors. + /// - a behavior makes sense only in some classes of a class hierarchy, + /// but not in others. + /// + public class VisitorSample + { + public static async Task Run() + { + Console.WriteLine("Behavioral - Visitor"); + List components = new List(); + components.Add(new ComponentA()); + components.Add(new ComponentB()); + + System.Console.WriteLine("With Visitor1 ...."); + Visitor1 visitor1 = new Visitor1(); + foreach (var component in components) + { + component.Visit(visitor1); + } + + System.Console.WriteLine("With Visitor2 ...."); + Visitor2 visitor2 = new Visitor2(); + foreach (var component in components) + { + component.Visit(visitor2); + } + } + + // implemented by components/hierarchy that needs to be visited + public interface IComponent { + void Visit(IVisitor visitor); + } + + public class ComponentA : IComponent { + public void IamComponentA() { + System.Console.WriteLine("IamComponentA"); + } + + public void Visit(IVisitor visitor) + { + visitor.VisitComponentA(this); + } + } + + public class ComponentB : IComponent { + public void SomeStuffFromComponentB() { + System.Console.WriteLine("SomeStuffFromComponentB"); + } + + public void Visit(IVisitor visitor) + { + visitor.VisitComponentB(this); + } + } + + // visitor interface declares a set of visiting methods that correspond + // to component classes. The signature of a visiting method allows the + // visitor to identify the exact class of the component that it's dealing + // with. + public interface IVisitor { + void VisitComponentA(ComponentA component); + void VisitComponentB(ComponentB component); + } + + public class Visitor1 : IVisitor + { + public void VisitComponentA(ComponentA component) + { + System.Console.Write($"From {this.GetType().Name} "); + component.IamComponentA(); + } + + public void VisitComponentB(ComponentB component) + { + System.Console.Write($"From {this.GetType().Name} "); + component.SomeStuffFromComponentB(); + } + } + + public class Visitor2 : IVisitor + { + public void VisitComponentA(ComponentA component) + { + System.Console.Write($"From {this.GetType().Name} "); + component.IamComponentA(); + } + + public void VisitComponentB(ComponentB component) + { + System.Console.Write($"From {this.GetType().Name} "); + component.SomeStuffFromComponentB(); + } + } + } +} \ No newline at end of file