Skip to content

Commit 97a15ee

Browse files
committed
Add Chain of Responsibility pattern implementation
Implemented the Chain of Responsibility design pattern with new classes: `Handler`, `LevelOneHandler`, `LevelTwoHandler`, `DefaultHandler`, and `Request` in the `DesignPatterns.Chain` namespace. Updated `Program.cs` to include a demo showcasing the pattern. Modified `README.md` to document the pattern, its purpose, example usage, and test references. Added `ChainTests` to verify the behavior of the pattern, ensuring proper handling of requests by different handlers. Integrated the pattern without affecting existing functionality.
1 parent 37d16e5 commit 97a15ee

File tree

8 files changed

+115
-2
lines changed

8 files changed

+115
-2
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace DesignPatterns.Chain;
2+
3+
public sealed class DefaultHandler : Handler
4+
{
5+
public override string Handle(Request request)
6+
{
7+
return $"Default handled: {request.Message}";
8+
}
9+
}

DesignPatterns/Chain/Handler.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace DesignPatterns.Chain;
2+
3+
public abstract class Handler
4+
{
5+
protected Handler? Next { get; private set; }
6+
7+
public Handler SetNext(Handler next)
8+
{
9+
Next = next;
10+
return next;
11+
}
12+
13+
public virtual string Handle(Request request)
14+
{
15+
if (Next != null) return Next.Handle(request);
16+
return "Unhandled";
17+
}
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DesignPatterns.Chain;
2+
3+
public sealed class LevelOneHandler : Handler
4+
{
5+
public override string Handle(Request request)
6+
{
7+
if (request.Level == 1) return $"LevelOne handled: {request.Message}";
8+
return base.Handle(request);
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DesignPatterns.Chain;
2+
3+
public sealed class LevelTwoHandler : Handler
4+
{
5+
public override string Handle(Request request)
6+
{
7+
if (request.Level == 2) return $"LevelTwo handled: {request.Message}";
8+
return base.Handle(request);
9+
}
10+
}

DesignPatterns/Chain/Request.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace DesignPatterns.Chain;
2+
3+
public sealed class Request
4+
{
5+
public int Level { get; }
6+
public string Message { get; }
7+
8+
public Request(int level, string message)
9+
{
10+
Level = level;
11+
Message = message ?? string.Empty;
12+
}
13+
}

DesignPatterns/Program.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using DesignPatterns.Facade;
1111
using DesignPatterns.Flyweight;
1212
using DesignPatterns.Proxy;
13+
using DesignPatterns.Chain;
1314

1415
Console.WriteLine("Factory pattern demo:");
1516

@@ -95,7 +96,19 @@
9596
nested.Add(child);
9697
nested.Add(new CircleGraphic());
9798
Console.WriteLine(nested.Draw());
98-
;
99+
100+
101+
// Chain of Responsibility demo
102+
Console.WriteLine();
103+
Console.WriteLine("Chain of Responsibility pattern demo:");
104+
var h1 = new LevelOneHandler();
105+
var h2 = new LevelTwoHandler();
106+
var def = new DefaultHandler();
107+
h1.SetNext(h2).SetNext(def);
108+
109+
Console.WriteLine(h1.Handle(new Request(1, "r1")));
110+
Console.WriteLine(h1.Handle(new Request(2, "r2")));
111+
Console.WriteLine(h1.Handle(new Request(99, "r3")));
99112

100113
// Decorator demo
101114
Console.WriteLine();

README.md

Lines changed: 18 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, and Proxy patterns.
6+
- `DesignPatterns` - Console demo showing Factory, Singleton, Builder, Prototype, Abstract Factory, Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy, and Chain of Responsibility 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`
@@ -16,6 +16,7 @@ Projects
1616
- Facade implementation: `DesignPatterns/Facade/*`
1717
- Flyweight implementation: `DesignPatterns/Flyweight/*`
1818
- Proxy implementation: `DesignPatterns/Proxy/*`
19+
- Chain of Responsibility implementation: `DesignPatterns/Chain/*`
1920
- `Tests` - xUnit tests covering the examples.
2021

2122
Included patterns and brief docs
@@ -157,6 +158,21 @@ Included patterns and brief docs
157158
img.Display(); // reuses loaded image
158159
```
159160
161+
- Chain of Responsibility Pattern
162+
- Purpose: Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
163+
- Example: `DesignPatterns/Chain/*` contains handlers `LevelOneHandler`, `LevelTwoHandler`, and `DefaultHandler` that process requests of different levels.
164+
- Usage snippet:
165+
166+
```csharp
167+
var h1 = new LevelOneHandler();
168+
var h2 = new LevelTwoHandler();
169+
var def = new DefaultHandler();
170+
h1.SetNext(h2).SetNext(def);
171+
Console.WriteLine(h1.Handle(new Request(1, "r1")));
172+
Console.WriteLine(h1.Handle(new Request(2, "r2")));
173+
Console.WriteLine(h1.Handle(new Request(99, "r3")));
174+
```
175+
160176
Tests
161177
- Tests are written with xUnit in the `Tests` project.
162178
- Factory tests: `Tests/ShapeFactoryTests.cs`
@@ -171,6 +187,7 @@ Tests
171187
- Facade tests: `Tests/FacadeTests.cs`
172188
- Flyweight tests: `Tests/FlyweightTests.cs`
173189
- Proxy tests: `Tests/ProxyTests.cs`
190+
- Chain tests: `Tests/ChainTests.cs`
174191
175192
Common commands
176193
- Build solution: `dotnet build`

Tests/ChainTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using DesignPatterns.Chain;
2+
3+
namespace Tests;
4+
5+
public class ChainTests
6+
{
7+
[Fact]
8+
public void Chain_HandlesLevelOneAndTwoAndDefault()
9+
{
10+
var h1 = new LevelOneHandler();
11+
var h2 = new LevelTwoHandler();
12+
var def = new DefaultHandler();
13+
h1.SetNext(h2).SetNext(def);
14+
15+
var r1 = new Request(1, "r1");
16+
var r2 = new Request(2, "r2");
17+
var r3 = new Request(99, "r3");
18+
19+
Assert.Equal("LevelOne handled: r1", h1.Handle(r1));
20+
Assert.Equal("LevelTwo handled: r2", h1.Handle(r2));
21+
Assert.Equal("Default handled: r3", h1.Handle(r3));
22+
}
23+
}

0 commit comments

Comments
 (0)