2015-08-13 23:54:40 +02:00
---
layout: pattern
title: Memento
folder: memento
2015-08-15 18:03:05 +02:00
permalink: /patterns/memento/
2015-08-20 21:40:07 +02:00
categories: Behavioral
2021-05-19 10:49:05 -06:00
language: en
2015-09-22 18:25:56 +05:30
tags:
2019-12-13 22:22:11 +02:00
- Gang of Four
2015-08-13 23:54:40 +02:00
---
2016-01-03 21:14:30 +01:00
## Also known as
2020-08-29 21:51:32 +03:00
2016-01-03 21:14:30 +01:00
Token
2015-11-04 21:13:32 +02:00
2016-01-03 21:14:30 +01:00
## Intent
2020-08-29 21:51:32 +03:00
Without violating encapsulation, capture and externalize an object's internal state so that the
object can be restored to this state later.
2020-07-20 17:52:44 +03:00
## Explanation
2020-08-29 21:51:32 +03:00
2020-07-20 17:52:44 +03:00
Real world example
2020-08-29 21:51:32 +03:00
> We are working on astrology application where we need to analyze star properties over time. We are
> creating snapshots of star state using Memento pattern.
2020-07-20 17:52:44 +03:00
In plain words
2020-08-29 21:51:32 +03:00
> Memento pattern captures object internal state making it easy to store and restore objects in any
> point of time.
2020-07-20 17:52:44 +03:00
Wikipedia says
2020-08-29 21:51:32 +03:00
> The memento pattern is a software design pattern that provides the ability to restore an object to
> its previous state (undo via rollback).
2020-07-20 17:52:44 +03:00
**Programmatic Example**
Let's first define the types of stars we are capable to handle.
```java
public enum StarType {
2020-08-04 21:46:30 +00:00
SUN("sun"),
RED_GIANT("red giant"),
WHITE_DWARF("white dwarf"),
SUPERNOVA("supernova"),
2020-08-29 21:51:32 +03:00
DEAD("dead star");
...
2020-07-20 17:52:44 +03:00
}
```
2020-08-29 21:51:32 +03:00
Next, let's jump straight to the essentials. Here's the `Star` class along with the mementos that we
need manipulate. Especially pay attention to `getMemento` and `setMemento` methods.
2020-07-20 17:52:44 +03:00
```java
public interface StarMemento {
}
public class Star {
private StarType type;
private int ageYears;
private int massTons;
public Star(StarType startType, int startAge, int startMass) {
this.type = startType;
this.ageYears = startAge;
this.massTons = startMass;
}
public void timePasses() {
ageYears *= 2;
massTons *= 8;
switch (type) {
case RED_GIANT:
type = StarType.WHITE_DWARF;
break;
case SUN:
type = StarType.RED_GIANT;
break;
case SUPERNOVA:
type = StarType.DEAD;
break;
case WHITE_DWARF:
type = StarType.SUPERNOVA;
break;
case DEAD:
ageYears *= 2;
massTons = 0;
break;
default:
break;
}
}
StarMemento getMemento() {
2020-08-04 21:46:30 +00:00
var state = new StarMementoInternal();
2020-07-20 17:52:44 +03:00
state.setAgeYears(ageYears);
state.setMassTons(massTons);
state.setType(type);
return state;
}
void setMemento(StarMemento memento) {
2020-08-04 21:46:30 +00:00
var state = (StarMementoInternal) memento;
2020-07-20 17:52:44 +03:00
this.type = state.getType();
this.ageYears = state.getAgeYears();
this.massTons = state.getMassTons();
}
@Override
public String toString() {
return String.format("%s age: %d years mass: %d tons", type.toString(), ageYears, massTons);
}
private static class StarMementoInternal implements StarMemento {
private StarType type;
private int ageYears;
private int massTons;
2020-08-29 21:51:32 +03:00
// setters and getters ->
...
2020-07-20 17:52:44 +03:00
}
}
```
And finally here's how we use the mementos to store and restore star states.
```java
2020-08-04 21:46:30 +00:00
var states = new Stack< >();
var star = new Star(StarType.SUN, 10000000, 500000);
2020-07-20 17:52:44 +03:00
LOGGER.info(star.toString());
states.add(star.getMemento());
star.timePasses();
LOGGER.info(star.toString());
states.add(star.getMemento());
star.timePasses();
LOGGER.info(star.toString());
states.add(star.getMemento());
star.timePasses();
LOGGER.info(star.toString());
states.add(star.getMemento());
star.timePasses();
LOGGER.info(star.toString());
while (states.size() > 0) {
star.setMemento(states.pop());
LOGGER.info(star.toString());
}
```
2020-08-29 21:51:32 +03:00
Program output:
```
sun age: 10000000 years mass: 500000 tons
red giant age: 20000000 years mass: 4000000 tons
white dwarf age: 40000000 years mass: 32000000 tons
supernova age: 80000000 years mass: 256000000 tons
dead star age: 160000000 years mass: 2048000000 tons
supernova age: 80000000 years mass: 256000000 tons
white dwarf age: 40000000 years mass: 32000000 tons
red giant age: 20000000 years mass: 4000000 tons
sun age: 10000000 years mass: 500000 tons
```
2015-08-13 23:54:40 +02:00
2019-12-07 20:01:13 +02:00
## Class diagram
2020-08-29 21:51:32 +03:00
2015-08-13 23:54:40 +02:00

2016-01-03 21:14:30 +01:00
## Applicability
2020-08-29 21:51:32 +03:00
2016-01-03 21:14:30 +01:00
Use the Memento pattern when
2015-08-13 23:54:40 +02:00
2020-08-29 21:51:32 +03:00
* A snapshot of an object's state must be saved so that it can be restored to that state later, and
* A direct interface to obtaining the state would expose implementation details and break the
object's encapsulation
2015-08-13 23:54:40 +02:00
2016-01-03 21:14:30 +01:00
## Real world examples
2015-08-13 23:54:40 +02:00
2015-08-15 18:03:05 +02:00
* [java.util.Date ](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html )
2015-09-22 18:25:56 +05:30
2016-01-03 21:14:30 +01:00
## Credits
2015-09-22 18:25:56 +05:30
2020-07-06 13:31:07 +03:00
* [Design Patterns: Elements of Reusable Object-Oriented Software ](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59 )
2020-07-07 18:05:11 +03:00
* [Head First Design Patterns: A Brain-Friendly Guide ](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b )