The memento behavioral pattern allows you to save and later restore the state of an object even without full access to all properties.
You can use this pattern to save an object’s state so you can possibly restore the object at some later time back to what it was when the state was saved. You might wonder why you can’t just read the properties in your code and save everything you read. Because there could be either properties that are read-only or not exposed at all. You might be able to read a read-only property but you won’t be able to restore that property later.
Another option would be to just allow the object itself to save its own state and restore it. The problem with this is that the object then needs to manage the storage. What if your application wants to allow ten different saves or a hundred? That’s up to the rest of your application so it makes sense that your application should be the one to manage all this saved information.
This pattern describes a solution where you ask an originating object for its state in the form of another object called a memento. The code outside of the object, in other words, the rest of your application, has no access to the internal data in the memento object. All it can do is save the memento for possible use later. If the user does want to restore the state, then your application just passes the saved memento back to the original object. Since we’re back in the object that created the memento, it has full access to read the state and update it’s own properties so they match the memento.
This lets you restore an object without knowing about or even have access to all the data needed to put an object back into some previous state. Listen to the full episode about this pattern or you can also read the full transcript below.
The basic description says that this pattern lets you obtain an object’s internal state to an external object without violating encapsulation and then use the external object to restore the state back to what it was.
This is one of those scenarios where it’s not immediately obvious why it’s needed.
I’m going to use an example of a car engine to explain this design pattern. What methods and properties would a car engine class need? The methods start and stop come to mind as well as a property for how much fuel is being provided. This should be good enough to get started.
Start and stop are simple and don’t need any parameters. We can say that even if no fuel is being provided, that the engine will still draw a certain minimum amount. Otherwise, if you call start, the engine would die right away without fuel. Sure, we could work around this but I’m going to keep this simple.
The fuel property can be a number from 0 to 100 representing a percentage from no additional fuel beyond the minimum to some maximum rate. We should be able to get and set this property.
As it is now, it seems like we have everything we need. We could even add another property called isRunning that would be read only just so we don’t have to remember ourselves if start was called or not.
With these methods and properties we should have enough to be able to save the current state of the engine so we can put it back at some point, right?
Episode 72 described the command pattern that lets you implement a undo/redo feature. Maybe we have commands for manipulating the engine state and want the commands to be able to be undone.
We start out with a command to start the engine. No problem here.
Then the user decides to read an email for a while before coming back to the application that’s controlling the engine. Maybe this is an engine simulator or something. Anyway, the user decides to increase the fuel to make the engine run a little faster, then reads another email.
Coming back to the application, the user decides to undo the last command and go back to the moment when the fuel was increased. This seems like it’s also no problem, right? Just put the fuel percentage back and the command can even remember what it was before it was changed.
If that’s all there was to the simulator, then, yes, this would not need the memento pattern. I’m going to introduce another property now that’s very important for an engine simulator and that’s temperature. As an engine runs, it gradually gets hotter until other systems start working to control the temperature.
It makes sense to allow code outside of the engine to be able to change the fuel amount, but does it make sense to also allow outside code to change the temperature? Read the temperature, yes. But change it? I don’t think so.
This is a problem for our undo feature because we now have a property that is beyond it’s ability to put back. We can restore the fuel level but the temperature will still reflect a higher amount due to the engine having been running all this time while the user was reading email.
What we need is a way to restore everything, including the temperature. And we need to be able to do this without breaking our careful design. Remember that we really don’t want other code to change the temperature for valid reasons. I’ll explain how to do this right after this message from our sponsor.
( Message from Sponsor )
The way to get around this is to enlist the help of the engine class by writing some more code that implements the memento pattern. We can make use of the fact that the engine class itself is allowed to change the temperature. and we can still honor the design decisions that prevent any other code from changing the temperature.
All we have to do is ask the engine class for its state in the form of another class that only the engine class will have full access to. Our code can ask for the state as part of setting up the command that increased the fuel amount in the first place. Even though the application code cannot do anything with the state object, it can save it. This state object is called the memento because it remembers the state.
We just need a couple methods in the engine class to create a memento and to set a memento.
What makes up the memento? That’s up to the engine class. The memento is just another class with private data members so that no other code can access or change it in any way. The memento class just needs to grant the engine class sole access to the data.
The application can ask for a memento and the engine class can feel safe in storing all its private data inside the memento because it knows that it will be the only class that can ever gain access to the data again.
The application then just saves the memento as a black box. The term black box just means that whatever’s inside is off limits and unknown.
What will the application do with the memento after it’s been saved? Maybe nothing. It’s very possible that the memento will never be used. If it is used, as when the user decides to undo the last command, then the application can give it back to the engine by calling the setMemento method. Whenever a memento is set back to the original object that created it, then that object can put all of its internal state back the way it was.
We did all this without ever needing to break our design and allow code to be able to change the engine temperature directly.
You can use the memento pattern either on its own or together with the command pattern.