Skip to content

Commit 3a98693

Browse files
authored
Merge pull request #20 from ilopX/add-official-example-memento-pattern
Add "Memento" pattern, conceptual example from book.
2 parents a419d88 + 6e22bca commit 3a98693

File tree

5 files changed

+145
-7
lines changed

5 files changed

+145
-7
lines changed

CHANGELOG.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
## 0.14.0
2+
- Add "Memento" conceptual pattern
3+
14
## 0.13.0
2-
- Add "Observer" pattern from official book, rewritten from Java example.
5+
- Add "Observer" pattern from official book, rewritten from Java example
36

47
## 0.12.19
58
- Refactoring: reformatting and minor changes
69

710
## 0.12.5
8-
- Put "Shapes" prototype pattern to "Shapes" folder.
9-
- The list of patterns has been updated. Added links to projects.
11+
- Put "Shapes" prototype pattern to "Shapes" folder
12+
- The list of patterns has been updated. Added links to projects
1013

1114
## 0.12.0
12-
- Add "Command" pattern from official book, rewritten from Java example.
15+
- Add "Command" pattern from official book, rewritten from Java example
1316

1417
## 0.11.0
1518
- Add "Chain of Responsibility" pattern from official book, rewritten from Java example
@@ -35,7 +38,7 @@
3538
- Add bridge pattern. Device remote control
3639

3740
## 0.5.5
38-
- Add example "graphics engine" and "square round conflict" for adapter pattern
41+
- Add example "graphics engine" and "square round conflict" for adapter patter
3942
- Add description to prototype pattern
4043
- Fix class diagram for text graph
4144
- Add description Builder pattern, text formats

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ It contains **Dart** examples for all classic **GoF** design patterns.
1515
- [ ] Interpreter
1616
- [ ] [**Iterator**](https://refactoring.guru/design-patterns/iterator)
1717
- [ ] [**Mediator**](https://refactoring.guru/design-patterns/mediator)
18-
- [ ] [**Memento**](https://refactoring.guru/design-patterns/memento)
18+
- [x] [**Memento**](https://refactoring.guru/design-patterns/memento) [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/memento/conceptual)]
1919
- [x] [**Observer**](https://refactoring.guru/design-patterns/observer) - [[Open-Close Editor Events](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/open_close_editor_events)]
2020
- [ ] [**State**](https://refactoring.guru/design-patterns/state)
2121
- [ ] [**Template Method**](https://refactoring.guru/design-patterns/template-method)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Memento pattern
2+
Memento is a behavioral design pattern that lets you save and restore the previous state of an
3+
object without revealing the details of its implementation.
4+
5+
Tutorial: [here](https://refactoring.guru/design-patterns/memento).
6+
7+
## Conceptual Editor example
8+
This example uses the Memento pattern alongside the Command pattern for storing snapshots of the
9+
complex text editor’s state and restoring an earlier state from these snapshots when needed.
10+
11+
More detailed explanation on [RefactoringGuru](https://refactoring.guru/design-patterns/memento?#pseudocode).
12+
13+
### Diagram:
14+
![image](https://user-images.githubusercontent.com/8049534/151352367-c97db094-fc87-4eb2-9210-581914c57ced.png)
15+
16+
### Client code:
17+
```dart
18+
void main() {
19+
final editor = Editor('New Document');
20+
final firstState = Command.makeBackup(editor);
21+
editor.text += ' add text';
22+
final secondState = Command.makeBackup(editor);
23+
24+
print('Current state: "${editor.text}"');
25+
26+
firstState.undo();
27+
print('First state: "${editor.text}"');
28+
29+
secondState.undo();
30+
print('Second state: "${editor.text}"');
31+
}
32+
```
33+
34+
**Output:**
35+
```
36+
Current state: "New Document add text"
37+
First state: "New Document"
38+
Second state: "New Document add text"
39+
```
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
void main() {
2+
final editor = Editor('New Document');
3+
final firstState = Command.makeBackup(editor);
4+
editor.text += ' add text';
5+
final secondState = Command.makeBackup(editor);
6+
7+
print('Current state: "${editor.text}"');
8+
9+
firstState.undo();
10+
print('First state: "${editor.text}"');
11+
12+
secondState.undo();
13+
print('Second state: "${editor.text}"');
14+
}
15+
16+
/// EN: The originator holds some important data that may change over
17+
/// time. It also defines a method for saving its state inside a
18+
/// memento and another method for restoring the state from it.
19+
///
20+
/// RU: Класс создателя должен иметь специальный метод, который.
21+
/// сохраняет состояние создателя в новом объекте-снимке.
22+
class Editor {
23+
var text = '';
24+
var curX = 0;
25+
var curY = 0;
26+
var selectionWidth = 0;
27+
28+
Editor(this.text);
29+
30+
/// EN: Saves the current state inside a memento.
31+
Snapshot createSnapshot() {
32+
/// EN: Memento is an immutable object; that's why the
33+
/// originator passes its state to the memento's
34+
/// constructor parameters.
35+
///
36+
/// RU: Снимок — неизменяемый объект, поэтому Создатель
37+
/// передаёт все своё состояние через параметры
38+
/// конструктора.
39+
return Snapshot(this, text, curX, curY, selectionWidth);
40+
}
41+
}
42+
43+
/// EN: The memento class stores the past state of the editor.
44+
///
45+
/// RU: Снимок хранит прошлое состояние редактора.
46+
class Snapshot {
47+
final Editor _editor;
48+
final String _text;
49+
final int _curX;
50+
final int _curY;
51+
final int _selectionWidth;
52+
53+
Snapshot(
54+
this._editor,
55+
this._text,
56+
this._curX,
57+
this._curY,
58+
this._selectionWidth,
59+
);
60+
61+
/// EN: At some point, a previous state of the editor can be
62+
/// restored using a memento object.
63+
///
64+
/// RU: В нужный момент владелец снимка может восстановить
65+
/// состояние редактора.
66+
void restore() {
67+
_editor
68+
..text = _text
69+
..curX = _curX
70+
..curY = _curY
71+
..selectionWidth = _selectionWidth;
72+
}
73+
}
74+
75+
/// EN: A command object can act as a caretaker. In that case, the
76+
/// command gets a memento just before it changes the
77+
/// originator's state. When undo is requested, it restores the
78+
/// originator's state from a memento.
79+
///
80+
/// RU: Опекуном может выступать класс команд (см. паттерн Команда).
81+
/// В этом случае команда сохраняет снимок состояния объекта-
82+
/// получателя, перед тем как передать ему своё действие. А в
83+
/// случае отмены команда вернёт объект в прежнее состояние.
84+
class Command {
85+
Snapshot _backup;
86+
87+
Command._(this._backup);
88+
89+
factory Command.makeBackup(Editor editor) {
90+
return Command._(editor.createSnapshot());
91+
}
92+
93+
void undo() {
94+
_backup.restore();
95+
}
96+
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: design_patterns_dart
22
description: Dart examples for all classic GoF design patterns.
3-
version: 0.13.0
3+
version: 0.14.0
44
homepage: https://refactoring.guru/design-patterns
55
repository: https://github.com/RefactoringGuru/design-patterns-dart
66
issue_tracker: https://github.com/RefactoringGuru/design-patterns-dart/issue

0 commit comments

Comments
 (0)