我想学会设计模式之备忘录模式
这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
备忘录模式
:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算。
什么是备忘录模式?
备忘录模式:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算。
注意:备忘录模式实现,不能破坏原始封装。也就是说,能拿到内部状态,将其保存在外部。
优缺点
优点
- 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
- 当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
缺点
- 如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
- 资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。
应用场景
最典型的例子是“斐波那契数列”递归实现。
不借助备忘录模式,数据一大,就容易爆栈;借助备忘录,算法的时间复杂度可以降低到O(n)。除此之外,数据的缓存等也是常见应用场景。
实现
场景:下棋例子,可以下棋,悔棋,撤销悔棋等
@Data
@AllArgsConstructor
class Chessman {
private String label;
private int x;
private int y;
//保存状态
public ChessmanMemento save() {
return new ChessmanMemento(this.label, this.x, this.y);
}
//恢复状态
public void restore(ChessmanMemento memento) {
this.label = memento.getLabel();
this.x = memento.getX();
this.y = memento.getY();
}
public void show() {
System.out.println(String.format("棋子<%s>:当前位置为:<%d, %d>", this.getLabel(), this.getX(), this.getY()));
}
}
class MementoCaretaker {
//定义一个集合来存储备忘录
private ArrayList mementolist = new ArrayList();
public ChessmanMemento getMemento(int i) {
return (ChessmanMemento) mementolist.get(i);
}
public void addMemento(ChessmanMemento memento) {
mementolist.add(memento);
}
}
@Data
@AllArgsConstructor
class ChessmanMemento {
private String label;
private int x;
private int y;
}
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);
play(chess);
chess.setY(4);
play(chess);
chess.setX(5);
play(chess);
undo(chess, index);
undo(chess, index);
redo(chess, index);
redo(chess, index);
}
//下棋,同时保存备忘录
public static void play(Chessman chess) {
mc.addMemento(chess.save());
index++;
chess.show();
}
//悔棋,撤销到上一个备忘录
public static void undo(Chessman chess, int i) {
System.out.println("******悔棋******");
index--;
chess.restore(mc.getMemento(i - 1));
chess.show();
}
//撤销悔棋,恢复到下一个备忘录
public static void redo(Chessman chess, int i) {
System.out.println("******撤销悔棋******");
index++;
chess.restore(mc.getMemento(i + 1));
chess.show();
}
}