[C# Design Patterns] The Memento Pattern

This lesson will cover the memento design pattern.

 

If you prefer to view this in a video, click here:

 

What it is

For non-programmers, a “memento” is something that helps you remember the past.

In programming, the Memento Design Pattern lets you save an object’s values, at a specific time, so you can recall them later. The “memento” is sometimes also called a “snapshot” – a picture of an object’s property values, at a certain time.

 

Why you’d want to use it

The most common use for this pattern is when you want the user to be able to edit an object’s value, but give them the option to “undo” their changes – and revert to the original values.

This is also used in state machines Рwhen an object goes through several state changes.  When you use it this way, you could save a list of memento objects Рone for each state change. Then, you can look at the history of the object, and (if needed) revert back several levels. For this situation, think of a shipment that goes from Ordered, to Packing, to Ready for Shipment, to Shipped, to Delivered.

 

Examples

 

VERY SIMPLE MEMENTO IMPLEMENTATION

This Customer class saves its original values (that were passed in through the constructor), so we can undo any changes to it.

 

 

After the constructor sets all the Customer object’s properties, it saves all the original values to private variables – the memento variables.

In this example. We have an IsDirty property, which can be used to see if any of the property values have been changed on the object.

If the user ever clicks the “Undo” button (on our imaginary program), the RevertToOriginal method will reset the Customer object’s properties to its original values.

 

CLEANER, MORE COMMON MEMENTO IMPLMENTATION

In this version, instead of having separate variables for each property’s original value, they are all passed to a memento object. And that object is saved as a private variable.

This isn’t very different from the first method. Both techniques store the original values in private variables. However, I prefer this method. You have fewer private variables, which makes the code easier to read. This way is also easier if you ever want to record multiple snapshots of the Customer object. That would let you easily add the ability for a user to “undo” multiple levels.

 

 

Notice that the CustomerMemento class is declared inside the Customer class, as a private class. That means CustomerMemento can only be used inside the Customer class – just like a private variable or method can only be used inside the class where it is declared.

Normally, I do not like declaring more than one class inside a file. However, CustomerMemento will never be used anyplace outside of the Customer class. So, this is one of the rare exceptions to the rule of “one class per file”. However, you could put CustomerMemento in its own file, if you wanted.

 

MULTIPLE MEMENTO IMPLEMENTATION

Here’s how to use a memento to track multiple snapshots of an object’s values. Instead of using a single private memento variable, we’ll use a private list of memento objects.

 

 

When the object is instantiated, the constructor calls the SaveMemento function, to create a memento object, and add it to the memento list. Whenever you call SaveMemento, it will create a new memento object, with the Customer object’s current values, and add it to the list.

RevertToOriginalValues will get the first memento, reset the Customer’s properties to that memento’s values, and remove all mementoes (other than the first one).

RevertToLastValues will get the most recent memento, reset the Customer’s properties to that memento’s values, and remove that memento from the list – unless it’s the first one.

With this technique, you can add an “undo” button to your program, and let the users go back through previous changes.

 

Where I’ve found it useful

I’ve worked on a few programs where we wanted to let users undo their changes, and we used the memento design pattern.

For the simple objects, we often used the first method, with private variables for each property. But, when the objects get larger (have more properties), I prefer to use a separate memento object.

Leave a Reply

Your email address will not be published. Required fields are marked *