Skip to content

Commit 45c138f

Browse files
committed
Add Visitor design pattern implementation and tests
Implemented the Visitor design pattern with `IVisitor`, `IElement`, `ElementA`, `ElementB`, `ConcreteVisitor`, and `ObjectStructure`. Added a demo in `Program.cs` showcasing the pattern and updated `README.md` with documentation, usage examples, and test references. Created `VisitorTests.cs` to verify the Visitor pattern functionality. Removed the unused "Composite demo" section from `Program.cs` to accommodate the new demo. Made minor formatting adjustments.
1 parent 9a220af commit 45c138f

File tree

4 files changed

+122
-2
lines changed

4 files changed

+122
-2
lines changed

DesignPatterns/Program.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using DesignPatterns.State;
1919
using DesignPatterns.Strategy;
2020
using DesignPatterns.TemplateMethod;
21+
using DesignPatterns.Visitor;
2122

2223
Console.WriteLine("Factory pattern demo:");
2324

@@ -89,7 +90,6 @@
8990
adv.VolumeUp();
9091
adv.Mute();
9192
Console.WriteLine($"Radio - Enabled: {radio.IsEnabled}, Volume: {radio.Volume}, Channel: {radio.Channel}");
92-
9393
// Composite demo
9494
Console.WriteLine();
9595
Console.WriteLine("Composite pattern demo:");
@@ -311,3 +311,17 @@
311311
{
312312
Console.WriteLine(msg);
313313
}
314+
315+
// Visitor demo
316+
Console.WriteLine();
317+
Console.WriteLine("Visitor pattern demo:");
318+
var structure = new ObjectStructure();
319+
structure.Add(new ElementA("alpha"));
320+
structure.Add(new ElementB(42));
321+
structure.Add(new ElementA("beta"));
322+
323+
var visitor = new ConcreteVisitor();
324+
structure.Accept(visitor);
325+
326+
Console.WriteLine("Visitor log:");
327+
foreach (var l in visitor.Log) Console.WriteLine(l);

DesignPatterns/Visitor/Visitor.cs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System.Collections.Generic;
2+
3+
namespace DesignPatterns.Visitor
4+
{
5+
public interface IVisitor
6+
{
7+
void Visit(ElementA element);
8+
void Visit(ElementB element);
9+
}
10+
11+
public interface IElement
12+
{
13+
void Accept(IVisitor visitor);
14+
}
15+
16+
public class ElementA : IElement
17+
{
18+
public string Name { get; }
19+
20+
public ElementA(string name) => Name = name;
21+
22+
public void Accept(IVisitor visitor) => visitor.Visit(this);
23+
24+
public override string ToString() => $"ElementA({Name})";
25+
}
26+
27+
public class ElementB : IElement
28+
{
29+
public int Value { get; }
30+
31+
public ElementB(int value) => Value = value;
32+
33+
public void Accept(IVisitor visitor) => visitor.Visit(this);
34+
35+
public override string ToString() => $"ElementB({Value})";
36+
}
37+
38+
public class ConcreteVisitor : IVisitor
39+
{
40+
public List<string> Log { get; } = new();
41+
42+
public void Visit(ElementA element)
43+
{
44+
Log.Add($"Visited A:{element.Name}");
45+
}
46+
47+
public void Visit(ElementB element)
48+
{
49+
Log.Add($"Visited B:{element.Value}");
50+
}
51+
}
52+
53+
public class ObjectStructure
54+
{
55+
private readonly List<IElement> _elements = new();
56+
57+
public void Add(IElement element) => _elements.Add(element);
58+
59+
public void Accept(IVisitor visitor)
60+
{
61+
foreach (var e in _elements)
62+
{
63+
e.Accept(visitor);
64+
}
65+
}
66+
}
67+
}

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Design Patterns Examples
33
This solution demonstrates simple design pattern examples in C# targeting .NET 10 (C# 14).
44

55
Projects
6-
- `DesignPatterns` - Console demo showing Factory, Singleton, Builder, Prototype, Abstract Factory, Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy, Chain of Responsibility, Command, Iterator, Mediator, Observer, State, Strategy, Template Method, and Memento patterns.
6+
- `DesignPatterns` - Console demo showing Factory, Singleton, Builder, Prototype, Abstract Factory, Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy, Chain of Responsibility, Command, Iterator, Mediator, Observer, State, Strategy, Template Method, Memento, and Visitor patterns.
77
- Factory implementation: `DesignPatterns/Factories`
88
- Singleton implementation: `DesignPatterns/Singleton/Logger.cs`
99
- Builder implementation: `DesignPatterns/Builder/HouseBuilder.cs` and `DesignPatterns/Builder/House.cs`
@@ -25,6 +25,7 @@ Projects
2525
- Strategy implementation: `DesignPatterns/Strategy/*`
2626
- Template Method implementation: `DesignPatterns/TemplateMethod/*`
2727
- Memento implementation: `DesignPatterns/Memento/*`
28+
- Visitor implementation: `DesignPatterns/Visitor/*`
2829
- `Tests` - xUnit tests covering the examples.
2930

3031
Included patterns and brief docs
@@ -291,6 +292,20 @@ Included patterns and brief docs
291292
Console.WriteLine(inv.GenerateReport());
292293
```
293294
295+
- Visitor Pattern
296+
- Purpose: Let you define a new operation without changing the classes of the elements on which it operates. Visitor separates an algorithm from the object structure it operates on.
297+
- Example: `DesignPatterns/Visitor/*` contains `IVisitor`, element types `ElementA`, `ElementB`, a `ConcreteVisitor` that logs visits, and `ObjectStructure` which holds elements and accepts a visitor.
298+
- Usage snippet:
299+
300+
```csharp
301+
var structure = new ObjectStructure();
302+
structure.Add(new ElementA("alpha"));
303+
structure.Add(new ElementB(42));
304+
var visitor = new ConcreteVisitor();
305+
structure.Accept(visitor);
306+
Console.WriteLine(string.Join("\n", visitor.Log));
307+
```
308+
294309
Tests
295310
- Tests are written with xUnit in the `Tests` project.
296311
- Factory tests: `Tests/ShapeFactoryTests.cs`
@@ -314,6 +329,7 @@ Tests
314329
- Strategy tests: `Tests/StrategyTests.cs`
315330
- Memento tests: `Tests/MementoTests.cs`
316331
- Template Method tests: `Tests/TemplateMethodTests.cs`
332+
- Visitor tests: `Tests/VisitorTests.cs`
317333
318334
Common commands
319335
- Build solution: `dotnet build`

Tests/VisitorTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using DesignPatterns.Visitor;
2+
3+
namespace Tests;
4+
5+
public class VisitorTests
6+
{
7+
[Fact]
8+
public void VisitorVisitsAllElements()
9+
{
10+
var structure = new ObjectStructure();
11+
structure.Add(new ElementA("alpha"));
12+
structure.Add(new ElementB(42));
13+
structure.Add(new ElementA("beta"));
14+
15+
var visitor = new ConcreteVisitor();
16+
structure.Accept(visitor);
17+
18+
Assert.Equal(3, visitor.Log.Count);
19+
Assert.Contains("Visited A:alpha", visitor.Log);
20+
Assert.Contains("Visited B:42", visitor.Log);
21+
Assert.Contains("Visited A:beta", visitor.Log);
22+
}
23+
}

0 commit comments

Comments
 (0)