Monday, October 12, 2009

Patterns - 037: Behavioral Patterns ( Memento )



The state of an object can be defined as the values of its properties or attributes at any given point of time. The Memento patter n is useful for designing a
mechanism to capture and store the state of an object so that subsequently, when needed, the object can be put back to this (previous) state.

This is more like an undo operation.

The Memento pattern can be used to accomplish this without exposing the object’s internal structure.

The object whose state needs to be captured is referred to as the
originator.

When a client wants to save the state of the originator, it requests the current state from the originator. The originator stores all those attributes that are required for restoring its state in a separate object referred to as a
Memento and returns it to the client.

A Memento object must hide the originator variable values from all objects except the originator. In other words, it should protect its internal state against access by objects other than the originator.

Example

Let us consider one application where customer data needs to be moved from a flat file to a relational database.

Let us consider three attributes — first name, last name and the credit-cardinformation in the flat file.

Whenever an invalid customer record is found, the process stops and prompts the user to correct the data and restart the process.

When the user restarts the process, the conversion process state is restored from the Memento object and the process resumes from where it stopped, instead of starting from the beginning of the source data file.


Storing the Memento in the memory is not an option in this case. The Memento needs to be stored to persistent media instead.

Instead of storing valid customer records in a relational database, the application generates a text file consisting of SQL insert statements.

DataConverter (Originator)

The DataConverter class is the implementer of the data conversion process.

ID
The instance variable ID constitutes the state of the DataConverter. It represents the customer ID of the last successfully processed customer record.

(Figure 32.1)

Memento
The Memento class is defined as an inner class within the DataConverter. The Memento is defined with its constructor and other methods as private.

In Java, a class can access the private members of its inner classes.


The DataConverter will be able to access these methods while they remain inaccessible to other objects. Because the state of the DataConverter needs to be preserved even after the application ends, the Memento object needs to be serialized to a file. Hence the Memento is designed to implement the java.io.Serializable interface to identify itself as a Serializable class.


In Java, a Serializable class must:
  • III Explicitly specify nonserializable attributes using the transient keyword
  • III Implement the java.io.Serializable interface
  • III Have access to the first zero argument constructor of its first non-Serializable super class

The client DCClient uses a helper MementoHandler object to serialize this Memento instance to a file. Once the data is corrected and the client DCClient is run again:
  • The client DCClient invokes the getMemento method on the MementoHandler requesting it for the stored Memento object.
  • The MementoHandler deserializes the previously serialized Mementoobject from the file and returns it to the client.
  • The client passes it to the DataConverter as an argument to its setMemento method. The DataConverter puts itself back to the state stored in the memento and resumes with the data conversion process from where it stopped during the previous run.

(Figure 32.2)

(Figure 32.3)



public class DCClient {

  public static void main(String[] args) {
      MementoHandler objMementoHandler = new MementoHandler();
      DataConverter objConverter = new DataConverter();

      objConverter.setMemento(objMementoHandler.getMemento());

      if (!(objConverter.process())) {
          System.out.println("Description: Invalid data - " +
                  "Process Stopped");
          System.out.println("Please correct the Data and " +
                  "Run the Application Again");
          objMementoHandler.setMemento(
                  objConverter.createMemento());
      }
  }
}

No comments:

Post a Comment