设计模式(十八)备忘录模式

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

设计模式(⼗⼋)备忘录模式
1、引⼊
1. 浏览器回退:浏览器⼀般有浏览记录,当我们在⼀个⽹页上点击⼏次链接之后,可在左上⾓点击左箭头回退到上⼀次的页⾯,然后也
可以点击右箭头重新回到当前页⾯;
2. 数据库备份与还原:⼀般的数据库都⽀持备份与还原操作,备份即将当钱已有的数据或者记录保留,还原即将已经保留的数据恢复到
对应的表中;
3. 编辑器撤销与重做:在编辑器上编辑⽂字,写错时可以按快捷键Ctrl+Z撤销,撤销后可以按Ctrl+y重做;
4. 虚拟机⽣成快照与恢复:虚拟机可以⽣成⼀个快照,当虚拟机发⽣错误时可以恢复到快照的样⼦;
5. GIT版本管理:Git是最常见的版本管理软件,每提交⼀个新版本,实际上Git就会把他们⾃动串成⼀条时间线,每个版本都有⼀个版本
号,使⽤git reset --hard 版本号,即可回到指定的版本,让代码时刻穿梭回到过去某个历史时刻;
6. 棋牌游戏悔棋:在棋牌游戏中,有时下快了可以悔棋,回退到上⼀步重新下。

2、定义:在不破坏封装的前提下,捕获⼀个对象的内部状态,并在该对象之外保存这个状态,这样可以在未来将对象恢复到原先保存的状态。

它是⼀种对象⾏为型模式,其别名为Token。

3、⾓⾊分析
(1)Originator(原发器):它是⼀个普通类,可以创建⼀个备忘录,并存储它的当前内部状态,也可以使⽤备忘录来恢复其内部状态,⼀般将需要保存内部状态的类设计为原发器;
(2)Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。

备忘录的设计⼀般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。

需要注意的是,除了原发器本⾝与负责⼈类之外,备忘录对象不能直接供其他类使⽤,原发器的设计在不同的编程语⾔中实现机制会有所不同;
(3)Caretaker(负责⼈):负责⼈⼜称为管理者,它负责保存备忘录,但是不能对备忘录的内容进⾏操作或检查。

在负责⼈类中可以存储⼀个或多个备忘录对象,它只负责存储对象,⽽不能修改对象,也⽆须知道对象的实现细节。

备忘录模式的核⼼是备忘录类以及⽤于管理备忘录的负责⼈类的设计。

4、代码实例
/**
* @author it-⼩林
* @desc 棋⼦类原发器⾓⾊
* @date 2021年09⽉18⽇ 15:10
*/
public class Chessman {
private String label;
private Integer x;
private Integer y;
public String getLabel() {
return label;
}
public void setLabel(String label) {
bel = 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;
}
public Chessman(String label, Integer x, Integer y) {
bel = label;
this.x = x;
this.y = y;
}
/**
* 保存状态
* @return
*/
public ChessmanMemento save(){
return new ChessmanMemento(bel, this.x, this.y);
}
/**
* 恢复
* @param chessmanMemento
*/
public void restore(ChessmanMemento chessmanMemento){
bel = chessmanMemento.getLabel();
this.x = chessmanMemento.getX();
this.y = chessmanMemento.getY();
}
/**
* 输出
*/
public void show(){
System.out.println(String.format("棋⼦<%s>:当前位置为:<%d, %d>", this.getLabel(), this.getX(), this.getY())); }
}
/**
* @author it-⼩林
* @desc 备忘录⾓⾊
* @date 2021年09⽉18⽇ 15:12
*/
public class ChessmanMemento {
private String label;
private Integer x;
private Integer y;
public String getLabel() {
return label;
}
public void setLabel(String label) {
bel = 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;
}
public ChessmanMemento(String label, Integer x, Integer y) {
bel = label;
this.x = x;
this.y = y;
}
}
/**
* @author it-⼩林
* @desc 负责⼈⾓⾊
* @date 2021年09⽉18⽇ 15:14
*/
public class MementoCaretaker {
private List<ChessmanMemento> mementoList = new ArrayList<>();
public ChessmanMemento getMemento(int i){
return mementoList.get(i);
}
public void addMemento(ChessmanMemento chessmanMemento){
mementoList.add(chessmanMemento);
}
}
/**
* @author it-⼩林
* @desc 客户端
* @date 2021年09⽉18⽇ 15:22
*/
public class Client {
private static int index = -1;
private static MementoCaretaker mementoCaretaker = new MementoCaretaker();
public static void main(String args[]){
Chessman chessman = new Chessman("车", 1, 1);
play(chessman);
chessman.setX(4);
play(chessman);
chessman.setY(5);
play(chessman);
undo(chessman, index);
undo(chessman, index);
redo(chessman, index);
redo(chessman, index);
}
/**
* 下棋,同时保存备忘录
* @param chessman
*/
public static void play(Chessman chessman){
mementoCaretaker.addMemento(chessman.save());
index++;
chessman.show();
}
/**
* 悔棋,撤销到上⼀个备忘录
* @param chessman
* @param i
*/
public static void undo(Chessman chessman, int i){
System.out.println("*******悔棋*********");
index--;
chessman.restore(mementoCaretaker.getMemento(i-1));
chessman.show();
}
/**
* 撤销悔棋,恢复到下⼀个备忘录
* @param chessman
* @param i
*/
public static void redo(Chessman chessman, int i){
System.out.println("*****撤销悔棋*****");
index++;
chessman.restore(mementoCaretaker.getMemento(i + 1));
chessman.show();
}
}
5、优缺点
(1)优点
它提供了⼀种状态恢复的实现机制,使得⽤户可以⽅便地回到⼀个特定的历史步骤,当新的状态⽆效或者存在问题时,可以使⽤暂时存储起来的备忘录将状态复原;
备忘录实现了对信息的封装,⼀个备忘录对象是⼀种原发器对象状态的表⽰,不会被其他代码所改动。

备忘录保存了原发器的状态,采⽤列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

(2)缺点
资源消耗过⼤,如果需要保存的原发器类的成员变量太多,就不可避免需要占⽤⼤量的存储空间,每保存⼀次对象的状态都需要消耗⼀定的系统资源。

6、使⽤场景
保存⼀个对象在某⼀个时刻的全部状态或部分状态,这样以后需要时它能够恢复到先前的状态,实现撤销操作;
防⽌外界对象破坏⼀个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象。

相关文档
最新文档