6.1. Memento¶
EN: Memento
PL: Pamiątka
Type: object
6.1.1. Pattern¶
Undo operation
Remembering state of objects

```plantuml
class Originator {
- content: str
+ create_state()
+ restore_state(state)
}
class Memento {
- content: str
}
class Caretaker {
- states: list[Memento]
+ push(state)
+ pop()
}
Memento -down[plain]-* Caretaker : composition
Originator -right[dashed]-> Memento : dependency
```
6.1.2. Problem¶

```plantuml
class Editor {
- content: str
+ create_state()
+ restore_state(state)
}
class EditorState {
- content: str
}
class History {
- states: list[EditorState]
+ push(state)
+ pop()
}
EditorState -down[plain]-* History : composition
Editor -right[dashed]-> EditorState : dependency
```
6.1.3. Solution¶

from dataclasses import dataclass, field
@dataclass(frozen=True)
class EditorState:
content: str
@dataclass
class History:
states: list[EditorState] = field(default_factory=list)
def push(self, state: EditorState) -> None:
self.states.append(state)
def pop(self) -> EditorState:
return self.states.pop()
class Editor:
content: str
def set_content(self, content: str) -> None:
self.content = content
def get_content(self) -> str:
return self.content
def create_state(self):
return EditorState(self.content)
def restore_state(self, state: EditorState):
self.content = state.content
if __name__ == '__main__':
editor = Editor()
history = History()
editor.set_content('a')
print(editor.content)
# a
editor.set_content('b')
history.push(editor.create_state())
print(editor.content)
# b
editor.set_content('c')
print(editor.content)
# c
editor.restore_state(history.pop())
print(editor.content)
# b
6.1.4. Assignments¶
"""
* Assignment: DesignPatterns Behavioral Memento
* Complexity: medium
* Lines of code: 29 lines
* Time: 13 min
English:
1. Implement Memento pattern
2. Create account history of transactions with:
a. `when: datetime` - date and time of a transaction
b. `amount: float` - transaction amount
3. Allow for transaction undo
4. Run doctests - all must succeed
Polish:
1. Zaimplementuj wzorzec Memento
2. Stwórz historię transakcji na koncie z:
a. `when: datetime` - data i czas transakcji
b: `amount: float` - kwota transakcji
3. Pozwól na wycofywanie (undo) transakcji
4. Uruchom doctesty - wszystkie muszą się powieść
Tests:
>>> account = Account()
>>> account.deposit(100.00)
>>> account.balance
100.0
>>> account.deposit(50.00)
>>> account.balance
150.0
>>> account.deposit(25.00)
>>> account.balance
175.0
>>> account.undo()
>>> account.balance
150.0
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Final
@dataclass
class Account:
balance: float = 0.0
def deposit(self, amount: float) -> None:
raise NotImplementedError
def undo(self):
raise NotImplementedError