#590 add explanation for Memento
This commit is contained in:
@ -12,8 +12,177 @@ tags:
|
||||
Token
|
||||
|
||||
## Intent
|
||||
Without violating encapsulation, capture and externalize an
|
||||
object's internal state so that the object can be restored to this state later.
|
||||
Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored
|
||||
to this state later.
|
||||
|
||||
## Explanation
|
||||
Real world example
|
||||
|
||||
> 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.
|
||||
|
||||
In plain words
|
||||
|
||||
> Memento pattern captures object internal state making it easy to store and restore objects in any point of time.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback).
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Let's first define the types of stars we are capable to handle.
|
||||
|
||||
```java
|
||||
public enum StarType {
|
||||
|
||||
SUN("sun"), RED_GIANT("red giant"), WHITE_DWARF("white dwarf"), SUPERNOVA("supernova"), DEAD(
|
||||
"dead star"), UNDEFINED("");
|
||||
|
||||
private String title;
|
||||
|
||||
StarType(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Next let's jump straight to the essentials. Here's the star class along with the mementos that we need manipulate.
|
||||
|
||||
```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() {
|
||||
|
||||
StarMementoInternal state = new StarMementoInternal();
|
||||
state.setAgeYears(ageYears);
|
||||
state.setMassTons(massTons);
|
||||
state.setType(type);
|
||||
return state;
|
||||
}
|
||||
|
||||
void setMemento(StarMemento memento) {
|
||||
|
||||
StarMementoInternal state = (StarMementoInternal) memento;
|
||||
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;
|
||||
|
||||
public StarType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(StarType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getAgeYears() {
|
||||
return ageYears;
|
||||
}
|
||||
|
||||
public void setAgeYears(int ageYears) {
|
||||
this.ageYears = ageYears;
|
||||
}
|
||||
|
||||
public int getMassTons() {
|
||||
return massTons;
|
||||
}
|
||||
|
||||
public void setMassTons(int massTons) {
|
||||
this.massTons = massTons;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And finally here's how we use the mementos to store and restore star states.
|
||||
|
||||
```java
|
||||
Stack<StarMemento> states = new Stack<>();
|
||||
Star star = new Star(StarType.SUN, 10000000, 500000);
|
||||
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());
|
||||
}
|
||||
|
||||
// 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
|
||||
```
|
||||
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
Reference in New Issue
Block a user