目录
一、前言
备忘录模式(Memento Pattern)是一种行为型设计模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在之后将该对象恢复到原来保存的状态。
备忘录模式由以下几个角色组成:
Originator(发起人):
负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复状态。Originator可根据需求决定Memento存储Originator的哪些内部状态
Memento(备忘录):
负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。
Caretaker(管理者):
负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查
整个备忘录模式的类图:
二、备忘录模式
比如常见的游戏存档,大部分会在进行某项重要任务之前存档,任务要是失败,可以读档,避免损失,这种情况使用备忘录模式就能很好实现存档读档。
根据备忘录模式,我们可以有以下代码:
首先创建Originator类:
java
/**
* @Author dengyifan
* @create 2024/4/30 14:04
* @description 发起人类
*/
public class Originator {
private String name;
private String address;
private Integer blood;
private Integer vigor;
public Originator(String name, String address, Integer blood, Integer vigor) {
this.name = name;
this.address = address;
this.blood = blood;
this.vigor = vigor;
}
public void recover(Memento memento){
this.name = memento.getName();
this.address = memento.getAddress();
this.blood = memento.getBlood();
this.vigor = memento.getVigor();
}
public Memento save(){
return new Memento(name,address,blood,vigor);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getBlood() {
return blood;
}
public void setBlood(Integer blood) {
this.blood = blood;
}
public Integer getVigor() {
return vigor;
}
public void setVigor(Integer vigor) {
this.vigor = vigor;
}
@Override
public String toString() {
return "Originator{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", blood=" + blood +
", vigor=" + vigor +
'}';
}
}
创建Memento类:
java
/**
* @Author dengyifan
* @create 2024/4/30 14:12
* @description 备忘录类,实际参数等是发起人里面的参数
*/
public class Memento {
private String name;
private String address;
private Integer blood;
private Integer vigor;
public Memento(String name, String address, Integer blood, Integer vigor) {
this.name = name;
this.address = address;
this.blood = blood;
this.vigor = vigor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getBlood() {
return blood;
}
public void setBlood(Integer blood) {
this.blood = blood;
}
public Integer getVigor() {
return vigor;
}
public void setVigor(Integer vigor) {
this.vigor = vigor;
}
}
创建Caretaker类:
java
/**
* @Author dengyifan
* @create 2024/4/30 14:12
* @description 管理类
*/
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
客户端调用测试:
java
/**
* @Author dengyifan
* @create 2024/4/30 14:12
* @description
*/
public class Client {
public static void main(String[] args) {
// 开始状态
Originator originator = new Originator("林克","海拉鲁", 30, 15);
System.out.println("初始状态:" + originator);
// 存档
Caretaker caretaker = new Caretaker();
caretaker.setMemento(originator.save());
// 消耗
originator.setBlood(5);
originator.setVigor(5);
System.out.println("消耗后:" + originator);
// 读档
originator.recover(caretaker.getMemento());
System.out.println("读取后:" + originator);
}
}
测试结果:
三、总结
优点与缺点:
优点:
1、提供了一种状态恢复的实现机制:当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。这对于一些需要频繁撤销操作或恢复状态的应用场景非常有用。
2、实现了对信息的封装:备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。这有助于保持代码的封装性和可维护性。
3、简化了发起人类:发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。这有助于减少发起人类的复杂性和工作量。
4、有利于保护封装边界:使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界
缺点:
1、资源消耗较大:如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间。每保存一次对象的状态都需要消耗一定的系统资源。
2、负责人可能无法预知存储空间消耗:当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。
使用场景:
1、撤销操作:备忘录模式适用于保存/恢复数据的相关业务场景,如Word中编写文档时,如果想要撤销之前的输入/删除操作,可以使用Ctrl+Z执行"撤销"操作。
2、状态恢复:在需要"后悔"的时候,将对象恢复到之前的状态,如游戏中的存档使用。