【设计模式与体系结构】行为型模式-备忘录模式
简介
备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不破坏封装性的前提下,捕获并保存对象的内部状态,以便在对象需要时,恢复到之前的状态。
备忘录模式的角色
发起人(Originator)类:负责创建一个备忘录对象,用以记录当前时刻自身的内部状态,并且可以使用备忘录对象恢复内部状态。
备忘录(Memento)类:用于存储发起人对象的内部状态。备忘录可以根据需求提供不同的访问权限,以确保状态的封装性。
管理者(Caretaker)类:负责保存备忘录对象,但不能对备忘录的内容进行操作或检查。
备忘录模式的优点
- 状态恢复:能够方便地恢复对象的历史状态
- 封装性好:将状态的保存和恢复的细节封装在备忘录对象中,不会暴露发起人的内部实现细节,符合封装性原则
- 职责分离:发起人对象的状态的保存与恢复的分离到了备忘录对象和管理者对象中,实现职责的分离,避免发起人对象的职责过于庞大
备忘录模式的缺点
- 资源消耗:若需要频繁地创建备忘录对象,可能会消耗大量的系统资源
- 维护成本:随着备忘录对象的增多,维护成本也会大大增加,特别是需要处理大量历史状态时
备忘录模式的使用场景
- 撤销操作:在各种软件应用中,例如备忘录、文本编辑器等需要实现撤销和重做功能的,用户执行的每一步操作都可以记录为一个备忘录,当需要撤销时,就可以从备忘录中恢复到以前的版本
- 数据库事务管理:数据库当事务发生错误时,数据可能需要回滚
- 游戏存档:在游戏开发中,玩家可以在游戏的某个节点保存游戏的状态,后续可以读取备忘录恢复游戏的状态
正文
下棋有一种操作叫做“悔棋”,下面就以悔棋操作作为案例进行代码分析
Chessman.java
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 void setLabel(String label) {
this.label = label;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public String getLabel() {
return (this.label);
}
public int getX() {
return (this.x);
}
public int getY() {
return (this.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();
}
}
ChessmanMemento.java
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 void setLabel(String label) {
this.label = label;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public String getLabel() {
return (this.label);
}
public int getX() {
return (this.x);
}
public int getY() {
return (this.y);
}
}
MementoCaretaker.java
public class MementoCaretaker {
private ChessmanMemento memento;
public ChessmanMemento getMemento() {
return memento;
}
public void setMemento(ChessmanMemento memento) {
this.memento = memento;
}
}