备忘录模式
一、介绍
备忘录设计模式(Memento Pattern),在不破坏封闭的前提下,捕获一个对象的内部状态,保存对象的某个状态,以便在适当的时候恢复对象,又叫做快照模式,属于行为模式。
备忘录模式实现的方式需要保证被保存的对象状态不能被对象从外部访问,
二、应用场景
- 玩游戏的时候肯定有存档功能,下一次登录游戏时可以从上次退出的地方继续游戏
- 棋盘类游戏的悔棋、数据库事务回滚
- 需要记录一个对象的内部状态时,为了允许用户取消不确定或者错误的操作,能够恢复到原先的状态
- 提供一个可回滚的操作,如ctrl+z、浏览器回退按钮
三、角色
- Originator: 发起者,记录当前的内部状态,并负责创建和恢复备忘录数据,允许访问返回到先前状态所需的所有数据,可以根据需要决定Memento存储自己的哪些内部状态
- Memento: 备忘录,负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态
- Caretaker: 管理者,对备忘录进行管理、保存和提供备忘录,只能将备忘录传递给其他角色
- Originator 和 Memento属性类似
四、优缺点
优点
- 给用户提供了一种可以恢复状态的机制
- 实现了信息的封装,使得用户不需要关心状态的保存细节
缺点
- 消耗更多的资源,而且每一次保存都会消耗一定的内存
五、代码
需要存储的对象
package com.lcy.study.design.memento;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Description 数据库数据
* @Author lcy
* @Date 2021/7/27 18:18
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MementoData {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
/**
* 备份数据
* @return com.lcy.study.design.memento.DatabaseMemento
* @author lcy
* @date 2021/7/27 18:21
**/
public DatabaseMemento saveMemento(){
return new DatabaseMemento(name,age);
}
/**
* 回滚数据
* @param databaseMemento 快照
* @author lcy
* @date 2021/7/27 18:22
**/
public void rollback(DatabaseMemento databaseMemento){
this.name = databaseMemento.getName();
this.age = databaseMemento.getAge();
}
}
备忘录对象,包含原对象属性
package com.lcy.study.design.memento;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @Description 备忘录对象--快照
* @Author lcy
* @Date 2021/7/27 18:18
*/
@AllArgsConstructor
@Data
public class DatabaseMemento {
/**
* 姓名
*/
private final String name;
/**
* 年龄
*/
private final int age;
}
备忘录管理类
package com.lcy.study.design.memento;
import lombok.Data;
/**
* @Description 快照管理者
* @Author lcy
* @Date 2021/7/27 18:24
*/
@Data
public class MementoCaretaker {
/**
* 快照
*/
private DatabaseMemento databaseMemento;
}
调用类
package com.lcy.study.design.memento;
/**
* @Description 快照调用类
* @Author lcy
* @Date 2021/7/27 18:25
*/
public class MementoMain {
public static void main(String[] args){
MementoCaretaker mementoCaretaker = new MementoCaretaker();
MementoData mementoData = new MementoData("张三",10);
//备份
mementoCaretaker.setDatabaseMemento(mementoData.saveMemento());
System.out.println("快照:"+mementoData);
mementoData.setAge(11);
System.out.println("修改:"+mementoData);
mementoData.rollback(mementoCaretaker.getDatabaseMemento());
System.out.println("回滚:"+mementoData);
}
}