Memento概述

Memento - 图1

UML概述

Memento - 图2

玩具代码案例1 - 模拟浏览器的回退&前进操作

备忘录发起者

Browser

  1. package online.javabook.gof.behavioral.patterns5.memento1.browser.context;
  2. import online.javabook.gof.behavioral.patterns5.memento1.browser.memento.History;
  3. import online.javabook.gof.behavioral.patterns5.memento1.browser.memento.Memento;
  4. public class Browser {
  5. private History history = new History();
  6. private String url;
  7. public void go(String url) {
  8. this.url = url;
  9. history.add(new Memento(url));
  10. System.out.println("->" + url);
  11. }
  12. public void back() {
  13. Memento memento = history.getUndo();
  14. this.url = memento.getState();
  15. System.out.println("<-" + url);
  16. }
  17. public void forward() {
  18. Memento memento = history.getRedo();
  19. this.url = memento.getState();
  20. System.out.println("->" + url);
  21. }
  22. }

备忘录回放

History

  1. package online.javabook.gof.behavioral.patterns5.memento1.browser.memento;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class History {
  5. private int index = -1;
  6. private List<Memento> mementoList = new ArrayList<Memento>();
  7. public void add(Memento state){
  8. mementoList.add(state);
  9. index++;
  10. }
  11. public Memento get(int index){
  12. return mementoList.get(index);
  13. }
  14. public Memento getUndo() {
  15. if (index == -1) {
  16. return null;
  17. }
  18. index = Math.max(0, --index);
  19. return mementoList.get(index);
  20. }
  21. public Memento getRedo() {
  22. if (index == mementoList.size()) {
  23. return null;
  24. }
  25. index = Math.min(mementoList.size() - 1, ++index);
  26. return mementoList.get(index);
  27. }
  28. }

备忘录状态

Memento

  1. package online.javabook.gof.behavioral.patterns5.memento1.browser.memento;
  2. public class Memento {
  3. private String url;
  4. public Memento(String url){
  5. this.url = url;
  6. }
  7. public String getState(){
  8. return url;
  9. }
  10. }

备忘录测试

Main

  1. package online.javabook.gof.behavioral.patterns5.memento1.browser.app;
  2. import online.javabook.gof.behavioral.patterns5.memento1.browser.context.Browser;
  3. public class Main {
  4. public static void main(String[] args) {
  5. Browser browser = new Browser();
  6. browser.go("http://www.1.com");
  7. browser.go("http://www.2.com");
  8. browser.go("http://www.3.com");
  9. browser.go("http://www.4.com");
  10. browser.go("http://www.5.com");
  11. browser.go("http://www.6.com");
  12. browser.back();
  13. browser.back();
  14. browser.back();
  15. browser.back();
  16. browser.back();
  17. browser.back();
  18. browser.back();
  19. browser.forward();
  20. browser.forward();
  21. browser.forward();
  22. browser.forward();
  23. browser.forward();
  24. browser.forward();
  25. browser.forward();
  26. browser.back();
  27. browser.back();
  28. browser.back();
  29. }
  30. }

Console

  1. ->http://www.1.com
  2. ->http://www.2.com
  3. ->http://www.3.com
  4. ->http://www.4.com
  5. ->http://www.5.com
  6. ->http://www.6.com
  7. <-http://www.5.com
  8. <-http://www.4.com
  9. <-http://www.3.com
  10. <-http://www.2.com
  11. <-http://www.1.com
  12. <-http://www.1.com
  13. <-http://www.1.com
  14. ->http://www.2.com
  15. ->http://www.3.com
  16. ->http://www.4.com
  17. ->http://www.5.com
  18. ->http://www.6.com
  19. ->http://www.6.com
  20. ->http://www.6.com
  21. <-http://www.5.com
  22. <-http://www.4.com
  23. <-http://www.3.com

玩具代码案例2 - 图形编辑器与备忘录模式

图形编辑器中的redo/undo可能是备忘录模式的源头,这个案例中我们结合了命令模式(命令即状态)和备忘录模式

备忘录发起者

GraphEditor

  1. package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.context;
  2. import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.ColorCommand;
  3. import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.IGraphCommand;
  4. import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.MoveCommand;
  5. import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen.GraphCommandHistory;
  6. import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen.GraphCommandMemento;
  7. import java.awt.*;
  8. public class GraphEditor {
  9. private GraphCommandHistory history = new GraphCommandHistory();
  10. private Shape shape = new Shape();
  11. public void color(Color newColor) {
  12. IGraphCommand command = new ColorCommand(newColor);
  13. command.execute(shape);
  14. GraphCommandMemento memento = new GraphCommandMemento(command);
  15. history.add(memento);
  16. System.out.println("->" + shape);
  17. }
  18. public void move(Point newPoint) {
  19. IGraphCommand command = new MoveCommand(newPoint);
  20. command.execute(shape);
  21. GraphCommandMemento memento = new GraphCommandMemento(command);
  22. history.add(memento);
  23. System.out.println("->" + shape);
  24. }
  25. public void undo() {
  26. GraphCommandMemento memento = history.getUndo();
  27. IGraphCommand command = memento.getState();
  28. command.execute(shape);
  29. System.out.println("<-" + shape);
  30. }
  31. public void redo() {
  32. GraphCommandMemento memento = history.getRedo();
  33. IGraphCommand command = memento.getState();
  34. command.execute(shape);
  35. System.out.println("->" + shape);
  36. }
  37. }

备忘录回放

History

  1. package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class GraphCommandHistory {
  5. private int index = -1;
  6. private List<GraphCommandMemento> mementoList = new ArrayList<GraphCommandMemento>();
  7. public void add(GraphCommandMemento state){
  8. mementoList.add(state);
  9. index++;
  10. }
  11. public GraphCommandMemento get(int index){
  12. return mementoList.get(index);
  13. }
  14. public GraphCommandMemento getUndo() {
  15. if (index == -1) {
  16. return null;
  17. }
  18. index = Math.max(0, --index);
  19. return mementoList.get(index);
  20. }
  21. public GraphCommandMemento getRedo() {
  22. if (index == mementoList.size()) {
  23. return null;
  24. }
  25. index = Math.min(mementoList.size() - 1, ++index);
  26. return mementoList.get(index);
  27. }
  28. }

备忘录状态

Memento

  1. package online.javabook.gof.behavioral.patterns5.memento2.grapheditor.memen;
  2. import online.javabook.gof.behavioral.patterns5.memento2.grapheditor.command.IGraphCommand;
  3. public class GraphCommandMemento {
  4. private IGraphCommand graphCommand;
  5. public GraphCommandMemento(IGraphCommand graphCommand){
  6. this.graphCommand = graphCommand;
  7. }
  8. public IGraphCommand getState(){
  9. return graphCommand;
  10. }
  11. }

备忘录命令

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]}