Home
Core Java
Java
JDBC
Servlets
JSP
EJB
JMS
Struts
Spring
Hibernate
JSF
RMI
CORBA
J2ME
Performance
Tomcat
Weblogic
Design Patterns
Junit
XML
UML
DB2 & SQL
ANT
Free Gift
Contact Us

XML RSS
What is this?
Add to My Yahoo!
Add to My MSN
Add to Google
 

Behavorial Pattern

Memento Pattern

Your Ad Here

Creational patterns Structural patterns Behavioral pattern J2EE patterns
Abstract Factory Adapter  Chain of Responsibility
MVC 
Builder Bridge  Command  Business Delegate
Factory method Composite  Interpreter  Composite Entity
Prototype Decorator  Iterator  Data Access Object
Singleton Façade
Mediator  Front Controller

Flyweight  Memento  Intercepting Filter

Proxy  Observer  Service Locator


State  Transfer Object


Strategy 


Template Method



Visitor 

Memento Pattern



Define memento pattern
To record an object internal state without violating encapsulation and reclaim it later without knowledge of the original object.

Where to use & benefits
Let some info in an object to be available by another object by using default access control.
Save some info for later uses.
Need undo/redo features.
Used in database transaction.

Related patterns include
  • Command, which supports undo or redo features, whereas a memento keeps state of an object.
  • Iterator, which provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation, whereas a memento can be used for iteration.

Your Ad Here
Example of memento pattern
To design a program with Memento feature is used to combine several design patterns like Command, Mediator or Iterator.

Here is an example expanded from Mediator example.

To show the Memento design concept, we record a dice number. This is very simple program. The Memento class just holds a number.

class Memento {
    int num;
    Memento(int c) {
       num = c;
    }
    int getNum() {
       return num;
    }
}

Then we combine Mediator and Command patterns to design three buttons and one label.The first button throws dice, the second button shows the dice number backward, and the third button clears number displayed. The label is used to display the dice number thrown. We use Math.random() method to get number from 1 to 6.

class BtnDice extends JButton implements Command {
    Mediator med;
    BtnDice(ActionListener al, Mediator m) {
        super("Throw Dice");
        addActionListener(al);
        med = m;
        med.registerDice(this);
    }
    public void execute() {
       med.throwit();
    }
}

class BtnClear extends JButton implements Command {
    Mediator med;
    BtnClear(ActionListener al, Mediator m) {
        super("Clear");
        addActionListener(al);
        med = m;
        med.registerClear(this);
    }
    public void execute() {
       med.clear();
    }
}
class BtnPrevious extends JButton implements Command {
    Mediator med;
    BtnPrevious(ActionListener al, Mediator m) {
        super("Previous");
        addActionListener(al);
        med = m;
        med.registerPrevious(this);
    }
    public void execute() {
       med.previous();
    }
}
class LblDisplay extends JLabel{
    Mediator med;
    LblDisplay (Mediator m) {
        super("0",JLabel.CENTER);
        med = m;
        med.registerDisplay(this);
        setBackground(Color.white);
        setBorder(new EtchedBorder(Color.blue, Color.green));
        Font font = new Font("Arial",Font.BOLD,40);
        setFont(font);
    }
}

The Mediator class will hold these participating objects and manipulate their relationships.

class Mediator {
    BtnDice btnDice;
    BtnPrevious btnPrevious;
    BtnClear btnClear;
    LblDisplay show;
    java.util.List list, undo;
    boolean restart = true;
    int counter = 0, ct = 0;
    //....
    Mediator() {
       list = new ArrayList();
       undo = new ArrayList();
    }
    void registerDice(BtnDice d) {
        btnDice = d;
    }
    void registerClear(BtnClear c) {
        btnClear = c;
    }
    void registerPrevious(BtnPrevious p) {
        btnPrevious = p;
    }
    void registerDisplay(LblDisplay d) {
        show = d;
    }
    void throwit() {
       show.setForeground(Color.black);
       int num = (int)(Math.random()*6 +1);
       int i = counter++;
       list.add(i, new Integer(num));
       undo.add(i, new Memento(num));
       show.setText(""+num);
    }
   
    void previous() {
       show.setForeground(Color.red);
       btnDice.setEnabled(false);
       if (undo.size() > 0) {      
           ct = undo.size()-1;
           Memento num = (Memento)undo.get(ct);
           show.setText(""+num.getNum());
           undo.remove(ct);
       }
       if (undo.size() == 0)
           show.setText("0");
    }
    void clear() {
        list = new ArrayList();
        undo = new ArrayList();
        counter = 0;
        show.setText("0");
        btnDice.setEnabled(true);
    }  
}

Finally, write a demo class.

class MementoDemo extends JFrame implements ActionListener {
    Mediator med = new Mediator();
    MementoDemo() {
       JPanel p = new JPanel();
       p.add(new BtnDice(this,med));
       p.add(new BtnPrevious(this,med));
       p.add(new BtnClear(this,med));
       JPanel dice = new JPanel();
       LblDisplay lbl = new LblDisplay(med);
       dice.add(lbl);
       getContentPane().add(dice, "Center");
       getContentPane().add(p, "South");
       setTitle("Memento pattern example");
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       setSize(400,200);
       setVisible(true);
    }
    public void actionPerformed(ActionEvent ae) {
        Command comd = (Command)ae.getSource();
        comd.execute();
    }
    public static void main(String[] args) {
        new MementoDemo();
    }
}

The complete workable program is as follows. Copy it, compile it and run it.

import javax.swing.*;
import java.awt.event.*;
import java.awt.FontMetrics;
import java.awt.*;
import java.util.*;
import javax.swing.border.*;

interface Command {
    void execute();
}
class Mediator {
    BtnDice btnDice;
    BtnPrevious btnPrevious;
    BtnClear btnClear;
    LblDisplay show;
    java.util.List list, undo;
    boolean restart = true;
    int counter = 0, ct = 0;
    //....
    Mediator() {
       list = new ArrayList();
       undo = new ArrayList();
    }
    void registerDice(BtnDice d) {
        btnDice = d;
    }
    void registerClear(BtnClear c) {
        btnClear = c;
    }
    void registerPrevious(BtnPrevious p) {
        btnPrevious = p;
    }
    void registerDisplay(LblDisplay d) {
        show = d;
    }
    void throwit() {
       show.setForeground(Color.black);
       int num = (int)(Math.random()*6 +1);
       int i = counter++;
       list.add(i, new Integer(num));
       undo.add(i, new Memento(num));
       show.setText(""+num);
    }
   
    void previous() {
       show.setForeground(Color.red);
       btnDice.setEnabled(false);
       if (undo.size() > 0) {      
           ct = undo.size()-1;
           Memento num = (Memento)undo.get(ct);
           show.setText(""+num.getNum());
           undo.remove(ct);
       }
       if (undo.size() == 0)
           show.setText("0");
    }
    void clear() {
        list = new ArrayList();
        undo = new ArrayList();
        counter = 0;
        show.setText("0");
        btnDice.setEnabled(true);
    }
   
}
class BtnDice extends JButton implements Command {
    Mediator med;
    BtnDice(ActionListener al, Mediator m) {
        super("Throw Dice");
        addActionListener(al);
        med = m;
        med.registerDice(this);
    }
    public void execute() {
       med.throwit();
    }
}

class BtnClear extends JButton implements Command {
    Mediator med;
    BtnClear(ActionListener al, Mediator m) {
        super("Clear");
        addActionListener(al);
        med = m;
        med.registerClear(this);
    }
    public void execute() {
       med.clear();
    }
}
class BtnPrevious extends JButton implements Command {
    Mediator med;
    BtnPrevious(ActionListener al, Mediator m) {
        super("Previous");
        addActionListener(al);
        med = m;
        med.registerPrevious(this);
    }
    public void execute() {
       med.previous();
    }
}
class Memento {
    int num;
    Memento(int c) {
       num = c;
    }
    int getNum() {
       return num;
    }
}
class LblDisplay extends JLabel{
    Mediator med;
    LblDisplay (Mediator m) {
        super("0",JLabel.CENTER);
        med = m;
        med.registerDisplay(this);
        setBackground(Color.white);
        setBorder(new EtchedBorder(Color.blue, Color.green));
        Font font = new Font("Arial",Font.BOLD,40);
        setFont(font);
    }
}
class MementoDemo extends JFrame implements ActionListener {
    Mediator med = new Mediator();
    MementoDemo() {
       JPanel p = new JPanel();
       p.add(new BtnDice(this,med));
       p.add(new BtnPrevious(this,med));
       p.add(new BtnClear(this,med));
       JPanel dice = new JPanel();
       LblDisplay lbl = new LblDisplay(med);
       dice.add(lbl);
       getContentPane().add(dice, "Center");
       getContentPane().add(p, "South");
       setTitle("Memento pattern example");
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       setSize(400,200);
       setVisible(true);
    }
    public void actionPerformed(ActionEvent ae) {
        Command comd = (Command)ae.getSource();
        comd.execute();
    }
    public static void main(String[] args) {
        new MementoDemo();
    }
}

Your Ad Here




footer for Memento Pattern page