备忘录模式
备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为型模式,其别名为Token。
Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。
Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。
Caretaker(负责人):负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节
示例1
以象棋中的悔棋为例说明。象棋走一步,将位置信息存储在memento中,可以悔一步棋
- 象棋类(Originator原发器)
public class Chessman {
private String label;
private Integer x;
private Integer y;
public Chessman(String label, Integer x, Integer y) {
this.label = label;
this.x = x;
this.y = y;
}
public ChessmanMemento getMemento() {
return new ChessmanMemento(this.label,this.x,this.y);
}
public void restoreMemento(ChessmanMemento memento) {
this.label = memento.getLabel();
this.x = memento.getX();
this.y = memento.getY();
}
@Override
public String toString() {
return "Chessman{" +
"label='" + label + '\'' +
", x=" + x +
", y=" + y +
'}';
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
public Integer getY() {
return y;
}
public void setY(Integer y) {
this.y = y;
}
}
- 备忘录(Memento)
public class ChessmanMemento {
private String label;
private Integer x;
private Integer y;
public ChessmanMemento(String label, Integer x, Integer y) {
this.label = label;
this.x = x;
this.y = y;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
public Integer getY() {
return y;
}
public void setY(Integer y) {
this.y = y;
}
}
- 负责管理类(Caretaker)
public class MementoCaretaker {
private ChessmanMemento memento;
public ChessmanMemento getMemento() {
return memento;
}
public void setMemento(ChessmanMemento memento) {
this.memento = memento;
}
}
- 测试类
public class Memento01Test {
public static void main(String[] args) {
Chessman chessman = new Chessman("车", 5, 6);
System.out.println("chessman = " + chessman);
ChessmanMemento memento = chessman.getMemento();
MementoCaretaker mementoCaretaker = new MementoCaretaker();
mementoCaretaker.setMemento(memento);
chessman.setX(6);
chessman.setY(8);
System.out.println("chessman = " + chessman);
chessman.restoreMemento(mementoCaretaker.getMemento());
System.out.println("chessman = " + chessman);
/**
* chessman = Chessman{label='车', x=5, y=6}
* chessman = Chessman{label='车', x=6, y=8}
* chessman = Chessman{label='车', x=5, y=6}
*/
}
}
上述例子只能恢复一步,如果需要恢复多步,可以采用列表在管理类中管理状态。
总结
-
优点
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态
- 实现了信息的封装,使得用户不需要关心状态的保存细节
-
缺点
- 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存
-
适用场景
- 保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时它能够恢复到先前的状态,实现撤销操作
-
应用
- ctrl+z
- 游戏存档
- 浏览器后退
- 数据库事务管理里
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。