Skip to content

Commit be75eac

Browse files
committed
Add Memento Design Pattern implementation
Implemented the Memento pattern with `TextMemento`, `TextEditor`, and `CareTaker` classes to enable state saving and restoration. Updated `Program.cs` to include a demo of the Memento pattern. Enhanced `README.md` to document the Memento pattern, including its purpose, example files, usage snippet, and test references. Added `MementoTests.cs` to verify the pattern's functionality, covering state saving/restoration and empty history handling. Improved code readability in `Program.cs` by renaming the loop variable in the `foreach` loop for `bob.Messages`.
1 parent 72de5a2 commit be75eac

File tree

6 files changed

+103
-2
lines changed

6 files changed

+103
-2
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DesignPatterns.Memento;
2+
3+
public class CareTaker
4+
{
5+
private readonly Stack<TextMemento> _history = new();
6+
7+
public void SaveState(TextMemento m) => _history.Push(m);
8+
9+
public TextMemento? PopState() => _history.Count > 0 ? _history.Pop() : null;
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace DesignPatterns.Memento;
2+
3+
public class TextEditor
4+
{
5+
public string Text { get; private set; } = string.Empty;
6+
7+
public TextMemento Save() => new TextMemento(Text);
8+
9+
public void Restore(TextMemento m)
10+
{
11+
if (m is null) throw new ArgumentNullException(nameof(m));
12+
Text = m.State;
13+
}
14+
15+
public void Type(string input) => Text += input;
16+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace DesignPatterns.Memento;
2+
3+
public sealed class TextMemento
4+
{
5+
internal string State { get; }
6+
7+
internal TextMemento(string state)
8+
{
9+
State = state ?? string.Empty;
10+
}
11+
}

DesignPatterns/Program.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using DesignPatterns.Chain;
1414
using DesignPatterns.Iterator;
1515
using DesignPatterns.Mediator;
16+
using DesignPatterns.Memento;
1617

1718
Console.WriteLine("Factory pattern demo:");
1819

@@ -158,7 +159,23 @@
158159

159160
alice.Send("Hello Bob");
160161
Console.WriteLine("Bob's messages:");
161-
foreach (var m in bob.Messages) Console.WriteLine(m);
162+
foreach (var msg in bob.Messages) Console.WriteLine(msg);
163+
164+
// Memento demo
165+
Console.WriteLine();
166+
Console.WriteLine("Memento pattern demo:");
167+
var editor = new TextEditor();
168+
var caretaker = new CareTaker();
169+
170+
editor.Type("Hello");
171+
caretaker.SaveState(editor.Save());
172+
173+
editor.Type(" World");
174+
Console.WriteLine($"Current text: {editor.Text}");
175+
176+
var m = caretaker.PopState();
177+
if (m != null) editor.Restore(m);
178+
Console.WriteLine($"Restored text: {editor.Text}");
162179

163180
// Decorator demo
164181
Console.WriteLine();

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, and Mediator 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, and Memento 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`
@@ -20,6 +20,7 @@ Projects
2020
- Command implementation: `DesignPatterns/Command/*`
2121
- Iterator implementation: `DesignPatterns/Iterator/*`
2222
- Mediator implementation: `DesignPatterns/Mediator/*`
23+
- Memento implementation: `DesignPatterns/Memento/*`
2324
- `Tests` - xUnit tests covering the examples.
2425

2526
Included patterns and brief docs
@@ -217,6 +218,20 @@ Included patterns and brief docs
217218
alice.Send("Hello Bob");
218219
```
219220
221+
- Memento Pattern
222+
- Purpose: Capture and externalize an object's internal state so it can be restored later without violating encapsulation.
223+
- Example: `DesignPatterns/Memento/*` contains `TextMemento`, `TextEditor` (originator), and `CareTaker` that stores mementos.
224+
- Usage snippet:
225+
226+
```csharp
227+
var editor = new TextEditor();
228+
var caretaker = new CareTaker();
229+
editor.Type("Hello");
230+
caretaker.SaveState(editor.Save());
231+
editor.Type(" World");
232+
editor.Restore(caretaker.PopState());
233+
```
234+
220235
Tests
221236
- Tests are written with xUnit in the `Tests` project.
222237
- Factory tests: `Tests/ShapeFactoryTests.cs`
@@ -235,6 +250,7 @@ Tests
235250
- Command tests: `Tests/CommandTests.cs`
236251
- Iterator tests: `Tests/IteratorTests.cs`
237252
- Mediator tests: `Tests/MediatorTests.cs`
253+
- Memento tests: `Tests/MementoTests.cs`
238254
239255
Common commands
240256
- Build solution: `dotnet build`

Tests/MementoTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using DesignPatterns.Memento;
2+
3+
namespace Tests;
4+
5+
public class MementoTests
6+
{
7+
[Fact]
8+
public void TextEditor_SaveAndRestore_Works()
9+
{
10+
var editor = new TextEditor();
11+
var caretaker = new CareTaker();
12+
13+
editor.Type("Hello");
14+
caretaker.SaveState(editor.Save());
15+
16+
editor.Type(" World");
17+
Assert.Equal("Hello World", editor.Text);
18+
19+
var m = caretaker.PopState();
20+
editor.Restore(m!);
21+
22+
Assert.Equal("Hello", editor.Text);
23+
}
24+
25+
[Fact]
26+
public void CareTaker_ReturnsNullWhenEmpty()
27+
{
28+
var caretaker = new CareTaker();
29+
Assert.Null(caretaker.PopState());
30+
}
31+
}

0 commit comments

Comments
 (0)