|
| 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 | +} |
0 commit comments