备忘录模式,备忘录模式属于行为型模式。它允许在不破坏封装的情况下捕获和恢复对象的内部状态。保存一个对象的某个状态,以便在适当的时候恢复对象,该模式通过创建一个备忘录对象来保存原始对象的状态,并将其存储在一个负责管理备忘录的负责人对象中。
备忘录模式的核心组成部分包括:
发起人(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()); //#4originator.getStateFromMemento(careTaker.get(0));System.out.println("取保存好的第一个状态: " + originator.getState()); // #2originator.getStateFromMemento(careTaker.get(1));System.out.println("取保存好的第二个状态: " + originator.getState()); // #3}
}
注意事项:
1、为了符合迪米特原则,还要增加一个管理备忘录的类。
2、为了节约内存,可使用原型模式+备忘录模式。