备忘录模式,备忘录模式属于行为型模式。它允许在不破坏封装的情况下捕获和恢复对象的内部状态。保存一个对象的某个状态,以便在适当的时候恢复对象,该模式通过创建一个备忘录对象来保存原始对象的状态,并将其存储在一个负责管理备忘录的负责人对象中。
备忘录模式的核心组成部分包括:
发起人(Originator):负责创建备忘录对象,并在需要的时候将自身状态保存到备忘录中。
备忘录(Memento):用于存储发起人对象的内部状态。
负责人(Caretaker):负责管理备忘录对象,可以对备忘录进行保存、恢复或删除等操作。
备忘录模式的优点包括:
- 封装了状态保存和恢复的细节:备忘录模式将保存和恢复对象状态的逻辑封装在备忘录对象中,发起人对象无需关心其具体实现。
- 支持撤销操作:通过存储历史状态的备忘录对象,可以轻松实现对象的撤销操作。
- 简化了原发器类:发起人对象只需关注自身的核心功能,而状态保存和恢复的责任交给备忘录和负责人对象。
备忘录模式也有一些限制和适用场景:
-
消耗内存:如果发起人对象的状态非常大或者频繁保存状态,可能会占用大量的内存空间。
-
额外开销:备忘录模式会引入额外的对象用于保存和管理状态,可能增加系统的开销。
其应用实例:
1、浏览器回退,前进
2、数据库备份与还原
3、Git版本管理
4、棋牌游戏悔棋
5. 编辑器当前 undo,redo.
使用场景:
1、需要保存/恢复数据的相关状态场景。
2、提供一个可回滚的操作。
/**
* 发起人(Originator)角色:
* 记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息
*/
public class Originator {
private String state;
public void setState(String state){
this.state = state;
}
public String getState(){
return state;
}
/**
* 生成一个备忘录对象
* @return
*/
public Memento saveStateToMemento(){
//TODO: .....将状态信息包装进去.
return new Memento(state);
}
/**
* 恢复关态
* @param Memento
*/
public void getStateFromMemento(Memento Memento){
//TODO:....从memento对象取出所有的状态进行恢复.
state = Memento.getState();
}
}
/**
* 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
*/
public class CareTaker {
//TODO:也可以是一个栈来保存.
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento state){
mementoList.add(state);
}
/**
* 获取第几步的状态信息
* @param index
* @return
*/
public Memento get(int index){
return mementoList.get(index);
}
/**
* 出栈操作
* @return
*/
public Memento pop(){
Memento last=mementoList.get( mementoList.size()-1 );
if( last!=null ) {
mementoList.remove(last);
}
return last;
}
}
/**
* 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
*/
public class Memento {
//TODO:要保存的状态信息
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
/**
* 测试类
*/
public class MementoPatternDemo {
public static void main(String[] args) {
//创建发起人(Originator)角色: 生成要保存的备忘的对象
Originator originator = new Originator();
//创建管理者(Caretaker):保存的列表
CareTaker careTaker = new CareTaker();
//记录状态
originator.setState("State #1"); //#1的状态没有保存
originator.setState("State #2");
//保存状态
careTaker.add( originator.saveStateToMemento()); //只保存了#2状态.
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");
System.out.println("当前状态: " + originator.getState()); //#4
originator.getStateFromMemento(careTaker.get(0));
System.out.println("取保存好的第一个状态: " + originator.getState()); // #2
originator.getStateFromMemento(careTaker.get(1));
System.out.println("取保存好的第二个状态: " + originator.getState()); // #3
}
}
注意事项:
1、为了符合迪米特原则,还要增加一个管理备忘录的类。
2、为了节约内存,可使用原型模式+备忘录模式。