CSC/ECE 517 Fall 2012/ch2b 2w62 pv: Difference between revisions
No edit summary |
|||
Line 95: | Line 95: | ||
// Wait for user | // Wait for user | ||
Console.Read(); | Console.Read(); | ||
== Summary == | |||
To sum up the post, the memento pattern is is used for saving encapsulated object state | |||
in an external object. The state can then be restored by demand. | |||
As I wrote the places that you’ll want to use the pattern are in scientific | |||
computing or in computer games but it can be helpful also in other places. | |||
The next post in the series will explain the state pattern. |
Revision as of 03:10, 20 November 2012
Introduction
The memento pattern is a pattern that provides the ability to restore an object to its previous state(via rollback). The memento pattern is implemented with two objects: the originator and a caretaker. The originator is some object that has an internal state. The caretaker is going to do something to the originator, but wants to be able to undo the change. The caretaker first asks the originator for a memento object. Then it does whatever operation it was going to do. To roll back to the state before the operations, it returns the memento object to the originator.
Motivation
It is sometimes necessary to capture the internal state of an object at some point and have the ability to restore the object to that state later in time. Such a case is useful in case of error or failure. Consider the case of a calculator object with an undo operation such a calculator could simply maintain a list of all previous operation that it has performed and thus would be able to restore a previous calculation it has performed. This would cause the calculator object to become larger, more complex, and heavyweight, as the calculator object would have to provide additional undo functionality and should maintain a list of all previous operations. This functionality can be moved out of the calculator class, so that an external (let's call it undo manager class) can collect the internal state of the calculator and save it. However providing the explicit access to every state variable of the calculator to the restore manager would be impractical and would violate the encapsulation principle.
Implementation
Memento
Stores internal state of the Originator object. The state can include any number of state variables.
The Memento must have two interfaces, an interface to the caretaker. This interface must not allow any operations or any access to internal state stored by the memento and thus honors encapsulation. The other interface is to the originator and allows the originator to access any state variables necessary to for the originator to restore previous state.
Originator
Creates a memento object capturing the originators internal state.
Use the memento object to restore its previous state.
Caretaker
Responsible for keeping the memento.
The memento is opaque to the caretaker, and the caretaker must not operate on it.
Example
The given example shows the three parts of the pattern: the Originator, the Memento and the Caretaker. The Caretaker is the repository for the Memento. You can also see that once the Memento object is created you can’t change the saved state and in order to save a new Memento you need to create it again. Implementation of the pattern in C#.
region Originator public class Originator<T> { #region Properties public T State { get; set; } #endregion #region Methods /// <summary> /// Creates a new memento to hold the current /// state /// </summary> /// <returns>The created memento</returns> public Memento<T> SaveMemento() { return (new Memento<T>(State)); } /// <summary> /// Restores the state which is saved in the given memento /// </summary> /// <param name="memento">The given memento</param> public void RestoreMemento(Memento<T> memento) { State = memento.State; } #endregion } #endregion #region Memento public class Memento<T> { #region Properties public T State { get; private set; } #endregion #region Ctor /// <summary> /// Construct a new memento object with the /// given state /// </summary> /// <param name="state">The given state</param> public Memento(T state) { State = state; } #endregion } #endregion #region Caretaker public class Caretaker<T> { #region Properties public Memento<T> Memento { get; set; } #endregion } #endregion
Usage
Originator<string> org = new Originator<string>(); org.State = "Old State";
// Store internal state in the caretaker object Caretaker<string> caretaker = new Caretaker<string>(); caretaker.Memento = org.SaveMemento(); Console.WriteLine("This is the old state: {0}", org.State); org.State = "New state"; Console.WriteLine("This is the new state: {0}", org.State);
// Restore saved state from the caretaker org.RestoreMemento(caretaker.Memento); Console.WriteLine("Old state was restored: {0}", org.State);
// Wait for user Console.Read();
Summary
To sum up the post, the memento pattern is is used for saving encapsulated object state in an external object. The state can then be restored by demand. As I wrote the places that you’ll want to use the pattern are in scientific computing or in computer games but it can be helpful also in other places. The next post in the series will explain the state pattern.