相信自己,请一定要相信自己
上一章简单介绍了中介者模式(二十一), 如果没有看过, 请观看上一章
一. 备忘录模式
引用 菜鸟教程里面备忘录模式介绍: https://www.runoob.com/design-pattern/memento-pattern.html
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。
备忘录模式属于行为型模式。
一.一 介绍
意图: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
主要解决: 所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,
这样可以在以后将对象恢复到原先保存的状态。
何时使用: 很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,
能够恢复到他原先的状态,使得他有"后悔药"可吃。
如何解决: 通过一个备忘录类专门存储对象状态。
关键代码: 客户不与备忘录类耦合,与备忘录管理类耦合。
应用实例: 1、后悔药。 2、打游戏时的存档。 3、Windows 里的 ctrl + z。 4、IE 中的后退。 5、数据库的事务管理。
优点:
1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点: 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
使用场景: 1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。
注意事项: 1、为了符合迪米特原则,还要增加一个管理备忘录的类。 2、为了节约内存,可使用原型模式+备忘录模式。
组成角色 | 具体 | 关系 |
---|---|---|
要保存的对象(originator) | GameRole | 对象(需要保存状态的对象) |
备忘录对象(Memento) | Memento | 备忘录对象,负责保存好记录,即Originator 内部状态 |
守护者对象(Caretaker) | Caretaker | 守护者对象,负责保存多个备忘录对象, 使用集合管理,提高效率 |
二. 备忘录实例
二.一 要保存的对象 GameRole
@Data
@Slf4j
public class GameRole {
/**
攻击力,防御力,血量
*/
private int vit;
private int def;
private int blood;
private String name;
private String field1;
public Memento createMemento() {
return Memento.builder()
.vit(vit)
.def(def)
.blood(blood)
.build();
}
// 恢复状态
public void recoverFromMemento( Memento memento) {
this.vit = memento.getVit();
this.def = memento.getDef();
this.blood = memento.getBlood();
}
public void display() {
log.info("当前 攻击力是: {}, 防御力: {},血量:{}",vit,def,blood);
}
}
二.二 备记录对象 Memento
@Data
@Builder
public class Memento {
/**
攻击力,防御力,血量
*/
private int vit;
private int def;
private int blood;
}
二.三 守护者对象 Caretaker
public class Caretaker {
private Map<String,Memento> statusMap = new HashMap<>();
// 根据 标识获取信息
public Memento getByStatus (String status) {
return statusMap.get(status);
}
public void saveStatus (String status, Memento memento) {
statusMap.put(status,memento);
}
}
二.四 客户端调用
@Test
public void oneTest() {
GameRole gameRole = new GameRole();
gameRole.setVit(0);
gameRole.setDef(0);
gameRole.setBlood(100);
log.info(">>> 打之前的数据是: ");
gameRole.display();
Memento memento = gameRole.createMemento();
Caretaker caretaker = new Caretaker();
caretaker.saveStatus("start",memento);
gameRole.setVit(20);
gameRole.setDef(20);
gameRole.setBlood(50);
log.info(">>> 打一半的数据是: ");
gameRole.display();
// 存个档
caretaker.saveStatus("middle",gameRole.createMemento());
// 回退到开始的版本
gameRole.recoverFromMemento(caretaker.getByStatus("start"));
gameRole.setVit(20);
gameRole.setDef(0);
gameRole.setBlood(0);
log.info(">>> 最后的数据是: ");
gameRole.display();
// 存个档
caretaker.saveStatus("end",gameRole.createMemento());
log.info(">>> 回退到开始的版本: ");
gameRole.display();
}
本章节的代码放置在 github 上:
https://github.com/yuejianli/DesignPattern/tree/develop/Memento
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!