提交 b907a2a9 编写于 作者: I Ilkka Seppälä

#590 add explanation for Memento

上级 467f647c
...@@ -12,8 +12,177 @@ tags: ...@@ -12,8 +12,177 @@ tags:
Token Token
## Intent ## Intent
Without violating encapsulation, capture and externalize an Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored
object's internal state so that the object can be restored to this state later. 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 ## Class diagram
![alt text](./etc/memento.png "Memento") ![alt text](./etc/memento.png "Memento")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册