Memento概述
UML概述
玩具代码案例1 - 模拟浏览器的回退&前进操作
备忘录发起者
Browser
package online.javabook.gof.behavioral.patterns5.memento1.browser.context;
import online.javabook.gof.behavioral.patterns5.memento1.browser.memento.History;
import online.javabook.gof.behavioral.patterns5.memento1.browser.memento.Memento;
public class Browser {
private History history = new History();
private String url;
public void go(String url) {
this.url = url;
history.add(new Memento(url));
System.out.println("->" + url);
}
public void back() {
Memento memento = history.getUndo();
this.url = memento.getState();
System.out.println("<-" + url);
}
public void forward() {
Memento memento = history.getRedo();
this.url = memento.getState();
System.out.println("->" + url);
}
}
备忘录回放
History
package online.javabook.gof.behavioral.patterns5.memento1.browser.memento;
import java.util.ArrayList;
import java.util.List;
public class History {
private int index = -1;
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento state){
mementoList.add(state);
index++;
}
public Memento get(int index){
return mementoList.get(index);
}
public Memento getUndo() {
if (index == -1) {
return null;
}
index = Math.max(0, --index);
return mementoList.get(index);
}
public Memento getRedo() {
if (index == mementoList.size()) {
return null;
}
index = Math.min(mementoList.size() - 1, ++index);
return mementoList.get(index);
}
}
备忘录状态
Memento
package online.javabook.gof.behavioral.patterns5.memento1.browser.memento;
public class Memento {
private String url;
public Memento(String url){
this.url = url;
}
public String getState(){
return url;
}
}
备忘录测试
Main
package online.javabook.gof.behavioral.patterns5.memento1.browser.app;
import online.javabook.gof.behavioral.patterns5.memento1.browser.context.Browser;
public class Main {
public static void main(String[] args) {
Browser browser = new Browser();
browser.go("http://www.1.com");
browser.go("http://www.2.com");
browser.go("http://www.3.com");
browser.go("http://www.4.com");
browser.go("http://www.5.com");
browser.go("http://www.6.com");
browser.back();
browser.back();
browser.back();
browser.back();
browser.back();
browser.back();
browser.back();
browser.forward();
browser.forward();
browser.forward();
browser.forward();
browser.forward();
browser.forward();
browser.forward();
browser.back();
browser.back();
browser.back();
}
}
Console
->http://www.1.com
->http://www.2.com
->http://www.3.com
->http://www.4.com
->http://www.5.com
->http://www.6.com
<-http://www.5.com
<-http://www.4.com
<-http://www.3.com
<-http://www.2.com
<-http://www.1.com
<-http://www.1.com
<-http://www.1.com
->http://www.2.com
->http://www.3.com
->http://www.4.com
->http://www.5.com
->http://www.6.com
->http://www.6.com
->http://www.6.com
<-http://www.5.com
<-http://www.4.com
<-http://www.3.com
玩具代码案例2 - 图形编辑器与备忘录模式
图形编辑器中的redo/undo可能是备忘录模式的源头,这个案例中我们结合了命令模式(命令即状态)和备忘录模式
备忘录发起者
GraphEditor
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.context;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.ColorCommand;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.IGraphCommand;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.MoveCommand;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen.GraphCommandHistory;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen.GraphCommandMemento;
import java.awt.*;
public class GraphEditor {
private GraphCommandHistory history = new GraphCommandHistory();
private Shape shape = new Shape();
public void color(Color newColor) {
IGraphCommand command = new ColorCommand(newColor);
command.execute(shape);
GraphCommandMemento memento = new GraphCommandMemento(command);
history.add(memento);
System.out.println("->" + shape);
}
public void move(Point newPoint) {
IGraphCommand command = new MoveCommand(newPoint);
command.execute(shape);
GraphCommandMemento memento = new GraphCommandMemento(command);
history.add(memento);
System.out.println("->" + shape);
}
public void undo() {
GraphCommandMemento memento = history.getUndo();
IGraphCommand command = memento.getState();
command.execute(shape);
System.out.println("<-" + shape);
}
public void redo() {
GraphCommandMemento memento = history.getRedo();
IGraphCommand command = memento.getState();
command.execute(shape);
System.out.println("->" + shape);
}
}
备忘录回放
History
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen;
import java.util.ArrayList;
import java.util.List;
public class GraphCommandHistory {
private int index = -1;
private List<GraphCommandMemento> mementoList = new ArrayList<GraphCommandMemento>();
public void add(GraphCommandMemento state){
mementoList.add(state);
index++;
}
public GraphCommandMemento get(int index){
return mementoList.get(index);
}
public GraphCommandMemento getUndo() {
if (index == -1) {
return null;
}
index = Math.max(0, --index);
return mementoList.get(index);
}
public GraphCommandMemento getRedo() {
if (index == mementoList.size()) {
return null;
}
index = Math.min(mementoList.size() - 1, ++index);
return mementoList.get(index);
}
}
备忘录状态
Memento
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.IGraphCommand;
public class GraphCommandMemento {
private IGraphCommand graphCommand;
public GraphCommandMemento(IGraphCommand graphCommand){
this.graphCommand = graphCommand;
}
public IGraphCommand getState(){
return graphCommand;
}
}
备忘录命令
IGraphCommand
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.context.Shape;
public interface IGraphCommand {
void execute(Shape shape);
}
ColorCommand
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.context.Shape;
import java.awt.*;
public class ColorCommand implements IGraphCommand {
private Color color;
public ColorCommand(Color newColor) {
this.color = newColor;
}
@Override
public void execute(Shape shape) {
shape.setColor(color);
}
}
MoveCommand
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.context.Shape;
import java.awt.*;
public class MoveCommand implements IGraphCommand {
private Point point;
public MoveCommand(Point newPoint) {
this.point = newPoint;
}
@Override
public void execute(Shape shape) {
shape.setPoint(point);
}
}
备忘录测试
Main
package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.app;
import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.context.GraphEditor;
import java.awt.*;
public class Main {
public static void main(String[] args) {
GraphEditor graphEditor = new GraphEditor();
graphEditor.color(Color.red);
graphEditor.color(Color.orange);
graphEditor.color(Color.yellow);
graphEditor.move(new Point(1,1));
graphEditor.move(new Point(2,2));
graphEditor.move(new Point(3,3));
graphEditor.undo();
graphEditor.undo();
graphEditor.redo();
graphEditor.redo();
}
}
Console
->Shape{color=java.awt.Color[r=255,g=0,b=0], point=java.awt.Point[x=0,y=0]}
->Shape{color=java.awt.Color[r=255,g=200,b=0], point=java.awt.Point[x=0,y=0]}
->Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=0,y=0]}
->Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=1,y=1]}
->Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=2,y=2]}
->Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=3,y=3]}
<-Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=2,y=2]}
<-Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=1,y=1]}
->Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=2,y=2]}
->Shape{color=java.awt.Color[r=255,g=255,b=0], point=java.awt.Point[x=3,y=3]}