前言
每个人都会有后悔的时候,可是人生没有后悔药,做过的事情无法再去后悔,软件设计中却是有这么一种后悔机制,叫做备忘录模式,它就是软件中的"后悔药"
什么是备忘录模式 Memento Pattern
在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样可以将对象恢复到原先保存的状态,它是一种对象行为型模式,有个别名叫做Token
备忘录模式的优点
(1)、它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储的备忘录将状态复原
(2)、备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动,备忘录保存了原发器的状态,采用列表,堆栈等集合来存储备忘录对象可以实现多次撤销操作。
备忘录模式的主要缺点
资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免地需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。
备忘录模式的适用场景
(1)、保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时就能恢复到先前的状态,实现撤销操作
(2)、防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象
备忘录模式的具体实现
目录结构
原发器
package com.company;
//象棋棋子类:原发器
public class Chessman {
private String label;
private int x;
private int y;
public Chessman(String label, int x, int y) {
this.label = label;
this.x = x;
this.y = y;
}
//保存状态
public ChessmanMemento save(){
return new ChessmanMemento(this.label,this.x,this.y);
}
//恢复状态
public void restore(ChessmanMemento memento){
this.label=memento.getLabel();
this.y=memento.getY();
this.x=memento.getX();
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
备忘录
package com.company;
//棋子备忘录
public class ChessmanMemento {
private String label;
private int x;
private int y;
public ChessmanMemento(String label, int x, int y) {
this.label = label;
this.x = x;
this.y = y;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
备忘录管理类
package com.company;
import java.util.ArrayList;
//象棋棋子备忘录管理类:负责人
public class MementoCaretaker {
/* private ChessmanMemento memento;
public ChessmanMemento getMemento() {
return memento;
}
public void setMemento(ChessmanMemento memento) {
this.memento = memento;
}*/
//定义一个集合来存储多个备忘录
private ArrayList mementoList=new ArrayList();
public ChessmanMemento getMemento(int i) {
return (ChessmanMemento) mementoList.get(i);
}
public void setMemento(ChessmanMemento memento) {
mementoList.add(memento);
}
}
测试类
package com.company;
public class Client {
private static int index = -1; //定义一个索引来记录当前状态所在的位置
private static MementoCaretaker mc = new MementoCaretaker();
public static void main(String[] args) {
Chessman chess = new Chessman("车", 1, 1);
display(chess);
chess.setX(4);
display(chess);
chess.setX(5);
display(chess);
undo(chess, index);
undo(chess, index);
redo(chess, index);
redo(chess, index);
}
//撤销悔棋
private static void redo(Chessman chess, int index) {
System.out.println("撤销悔棋");
index++;
chess.restore(mc.getMemento(index+1)); //恢复到下一个备忘录
System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "行。");
}
//悔棋
private static void undo(Chessman chess, int index) {
System.out.println("悔棋");
index--;
chess.restore(mc.getMemento(index-1)); //撤销到上个备忘录
System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "行。");
}
private static void display(Chessman chess) {
mc.setMemento(chess.save()); //保存在备忘录
index++;
System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "行。");
}
}
转载请注明出处,掌声送给社会人