Up tonight, I take a closer look at encapsulation in the memento pattern. I have a decent start on the pattern from last night, but I glossed over one of the important reasons behind the memento pattern. Per the Gang of Four book, the pattern is applicable when obtaining state would break encapsulation.
Currently, the caretaker of the pattern plays a song, remembers the state on occasion, and replays particularly good Mel Tormé songs:
List<String> replayer = [];
var scatMan = new VelvetFogMachine();
// ...
scatMan.play(
'New York, New York Medley',
'A Vintage Year'
);
replayer.add(scatMan.nowPlaying);
// ...
// The New York, New York Medley with George Shearing really is wonderful
scatMan.backTo(replayer[1]);
The encapsulation in this case is in the nowPlaying
getter of the VelvetFogMachine
. The nowPlaying
property in the Melvie-tastic VelvetFogMachine
is a list of strings (the title and album of the song):class VelvetFogMachine { List<String> _nowPlaying; // ... }There is not much to the state being exposed and what state is exposed comes directly from the caretaker (i.e. the title and album). So this may not be the ideal example. In addition to the song playing, I will try storing the current time within the song as well:
// The Memento class Playing { String title, album; double time; Playing(this.title, this.album, this.time); }If I tried to store this in the caretaker context, then I would certainly be breaking encapsulation. I would have to note the title, album and time at which the playing moved to the next song. Those aren't exactly related values, so this seems a better example.
Since I do not wish to expose the underlying implementation, the
replayer
can no longer be a list of strings. Instead, it needs to be a list of Playing
objects (i.e. a list of mementos): List<Playing> replayer = [];
Nothing else needs to change in the caretaker code. The scatMan
still plays songs by title and album. The nowPlaying
property still returns a memento—albeit a more complex one. The backTo()
method still takes the memento and uses it to restore state. Nothing really changed, but the more complex example better justifies the application of the pattern.The code in
VeletFogMachine
does not change much—it just needs to accommodate time now. The play()
method optionally accepts it: void play(String title, String album, [double time = 0.0]) {
print("Playing $title // $album @ ${time.toStringAsFixed(2)}");
_nowPlaying = new Playing(title, album, time);
}
And the backTo()
method needs to use the stored value to resume playing where it left off: // Restore from memento
void backTo(Playing memento) {
print(" *** Whoa! This was a good one, let's hear it again :) ***");
play(memento.title, memento.album, memento.time);
}
After adding a random number for the saved time, I have everything working—including restoring from the slightly more complex state:$ ./bin/play_melvie.dart ... Playing The Lady is a Tramp // The Velvet Frog: The Very Best of Mel Tormé @ 0.00 *** Whoa! This was a good one, let's hear it again :) *** Playing New York, New York Medley // A Vintage Year @ 1.28That seems a good place to stop for tonight. The memento seems a relatively simple pattern, which is making me feel the urge to move on to other patterns. But it is probably worth exploring a few more facets of the pattern in the next day or so. First up, I plan to see if there is a more "Darty" solution. Tomorrow.
Play with this code on DartPad: https://dartpad.dartlang.org/bf9c7454247a122030f9
Day #16
No comments:
Post a Comment