CSC/ECE 517 Fall 2012/ch2b 2w62 pv: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 79: Line 79:
     }
     }
     #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();

Revision as of 03:06, 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();