? 备忘录模式允许在不暴露对象实现细节的情况下捕获和恢复对象的内部状态。通过将对象的状态封装在备忘录对象中,并将备忘录对象保存在一个管理者对象中,可以在需要时回滚到对象之前的状态。
? 在现代办公场景中,备忘录模式可以应用于文档编辑工具中。以Office工具为例,当用户在云文档中进行编辑时,系统会自动将当前的文档内容保存在一个备忘录对象中,并将备忘录对象存储在云端的服务器上。每隔一段时间,系统会判断是否需要保存文档的状态,如果需要,则将当前的备忘录对象保存为一个快照,以便日后恢复文档的状态。
备忘录有两个接口,发起人能够通过宽接口访问数据,管理者只能看到窄接口,并将备忘录传递给其他对象
package com.technologystatck.designpattern.mode.memorandum;
import java.util.ArrayList;
import java.util.List;
public class Memorandum {
public static void main(String[] args) {
//创建发起人对象
Originator originator = new Originator();
originator.setState("State 1");
//创建管理者对象
Caretaker caretaker = new Caretaker();
//保存当前状态
caretaker.addMemento(originator.createMemento());
System.out.println("Current State:"+originator.getState());
//修改状态
originator.setState("State 2");
System.out.println("Current State:"+originator.getState());
//再次保存当前状态
caretaker.addMemento(originator.createMemento());
//恢复到先前状态
originator.restoreFromMemento(caretaker.getMemento(0));
System.out.println("Current State:"+originator.getState());
}
}
//创建发起人类:可以创建备忘录对象
class Originator{
//备忘录的状态
private String state;
public void setState(String state){
this.state=state;
}
public String getState(){
return state;
}
//创建备忘录对象
public Memento createMemento(){
return new Memento(this.state);
}
//通过备忘录对象恢复状态
public void restoreFromMemento(Memento memento){
state=memento.getState();
}
}
//创建备忘录类:保存发起人对象的状态
class Memento{
private String state;
//保存发起人的状态
public Memento(String state){
this.state=state;
}
public String getState(){
return state;
}
}
//创建备忘录管理者类:保存备忘录对象
class Caretaker{
private List<Memento> mementos=new ArrayList<>();
//添加备忘录对象
public void addMemento(Memento memento){
mementos.add(memento);
}
//获取备忘录对象
public Memento getMemento(int index){
return mementos.get(index);
}
}
小明正在设计一个简单的计数器应用,支持增加(Increment)和减少(Decrement)操作,以及撤销(Undo)和重做(Redo)操作,请你使用备忘录模式帮他实现。
输入包含若干行,每行包含一个字符串,表示计数器应用的操作,操作包括 “Increment”、“Decrement”、“Undo” 和 “Redo”。
对于每个 “Increment” 和 “Decrement” 操作,输出当前计数器的值,计数器数值从0开始 对于每个 “Undo” 操作,输出撤销后的计数器值。 对于每个 “Redo” 操作,输出重做后的计数器值。
package com.technologystatck.designpattern.mode.memorandum;
import java.util.Scanner;
import java.util.Stack;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Counter counter = new Counter();
//处理计数器应用的输入
while (scanner.hasNext()) {
String operation = scanner.next();
switch (operation) {
case "Increment":
counter.increment();
break;
case "Decrement":
counter.decrement();
break;
case "Undo":
counter.undo();
break;
case "Redo":
counter.redo();
break;
}
System.out.println(counter.getValue());
}
}
}
//备忘录
class Memento {
//备忘录的状态
private int value;
public Memento(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
//创建人
class Counter {
//表示计数器的值
private int value;
//撤销操作
private Stack<Memento> undoStack = new Stack<>();
//重做操作
private Stack<Memento> redoStack = new Stack<>();
//减少计数器的值
public void increment() {
//执行撤销操作时,需要清除一些无效的备忘录对象
//这些备忘录对象失去作用了需要清空
redoStack.clear();
//需要将当前状态保存在撤销栈中
undoStack.push(new Memento(value));
//计数器的值加1
value++;
}
//增加计数器值
public void decrement() {
//执行重做操作时,需要清除一些无效的备忘录对象
//这些备忘录对象失去作用了需要清空
redoStack.clear();
//需要将当前状态保存在撤销栈中
undoStack.push(new Memento(value));
//计数器的值加1
value--;
}
/**
* 当执行撤销或重做的操作时,都会将相关的备忘录对象
* 移动到另一个栈中,保证了操作的一致性
*/
//撤销操作
public void undo() {
//若撤销栈不为空,则将当前栈顶元素移动到重做栈中,
//并将当前栈顶元素的值赋给value变量
if (!undoStack.isEmpty()) {
redoStack.push(new Memento(value));
value = undoStack.pop().getValue();
}
}
//重做操作
public void redo() {
//若重做栈不为空,则将当前栈顶元素移动到撤销栈中
//并将当前栈顶元素的值赋给value变量
if (!redoStack.isEmpty()) {
undoStack.push(new Memento(value));
value = redoStack.pop().getValue();
}
}
//获取value值
public int getValue() {
return value;
}
}