备忘录模式(Memento Pattern)是一种行为型设计模式,它主要用于在软件系统中保存对象的内部状态,以便在后续操作中可以恢复到之前的状态。这种模式的主要目的是支持撤销操作,例如文本编辑器中的撤销和重做功能。备忘录模式可以帮助我们更好地管理对象的状态,提高系统的可维护性和可扩展性 。,,备忘录模式定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。 该模式又叫快照模式 。
1、发起人(Originator):负责创建备忘录对象,以及执行撤销和重做操作。
2、备忘录(Memento):用于存储对象的内部状态,备忘录可以是一个简单的数据结构,如一个字节数组或字符串,也可以是一个更复杂的对象,包含更多的状态信息。
3、监听者(Caretaker):负责管理备忘录对象,当备忘录对象不再需要时,将其存储起来,以便后续使用,监听者还可以提供一些额外的功能,如打印备忘录内容等。
备忘录模式的实现步骤如下:
1、我们需要定义一个抽象类,表示备忘录,这个抽象类包含一个私有的内部状态成员变量,以及一个获取内部状态的方法,这个抽象类还需要定义一个虚方法,用于比较两个备忘录对象的状态是否相等。
public abstract class Memento { private Object internalState; public Memento(Object internalState) { this.internalState = internalState; } public Object getInternalState() { return internalState; } public abstract boolean isSameStateAs(Memento other); }
2、我们需要定义一个具体的备忘录类,用于存储发起人的状态,这个具体的备忘录类继承自抽象的备忘录类,并实现isSameStateAs方法。
public class OriginatorStateMemento extends Memento { public OriginatorStateMemento(Object internalState) { super(internalState); } @Override public boolean isSameStateAs(Memento other) { if (!(other instanceof OriginatorStateMemento)) { return false; } return super.isSameStateAs(other); } }
3、我们需要定义一个发起人类,用于执行撤销和重做操作,这个发起人类包含一个私有的内部状态成员变量,以及一个获取当前状态的方法,这个发起人类还需要定义两个私有的方法,分别用于执行撤销操作和重做操作,这两个方法都需要传入一个备忘录对象作为参数。
public class Originator { private Object internalState; private List<Memento> mementoList; public Originator() { mementoList = new ArrayList<>(); } public void setInternalState(Object state) { originatorStateMemento = new OriginatorStateMemento(state); // create a new Memento to save the state for future use later on in the command chain. This will be our current "redo" point. We keep track of these in the list so that we can revert back to them if needed later on. If we are at the end of the list we need to remove the oldest one and add a new one to make room for the new one we just saved. This is what the addCommand method does. The same goes for the "undo" operation. When we call the "undo" method we simply pop the last element off of the list and run it again. If we are out of elements then there was nothing to do so we simply return without doing anything. The "redo" operation is similar except instead of calling the command's execute() method we call its reverse() method which will perform the same action in reverse order. So when we pop an element off of the list and run it again we are actually running it backwards. This allows us to "redo" actions as well as "undo" them. This is all done by maintaining a reference to each of the Mementos that were previously saved so that they can be used again later on in the command chain.