 |
| |
Behavorial Pattern
Memento Pattern
|
|
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.
|
|
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();
}
}
|
|
|

|
|