在生活中,我们犯错的时候,总想着能否从来一次的机会,虽然在现实中是很残酷的,但是在虚拟的网络中是可以从来的。比如PS的历史纪录,以及大多数软件的撤销命令。
备忘录(Memento)模式的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。
优点:
- 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
- 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
- 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
缺点:
- 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
模式的结构与实现
结构
- 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
- 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
实现
场景:计算器的历史记录功能
package com.wly.DesignPatterns;
import java.util.ArrayList;
import java.util.List;
/**
* @program: StudyDome
* @author: yuanzhang
* @create: 2021-01-21 10:39
**/
public class MementoPattern {
public static void main(String[] args) {
Calculator calculator = new Calculator();
Caretaker caretaker = new Caretaker();
System.out.println("第一次计算操作:");
calculator.add(1,2);
System.out.println(calculator.getHistory());
//将操作记录保存
caretaker.setMemo(calculator.addMemo());
System.out.println("第二次计算操作:");
calculator.multiply(123,321);
System.out.println(calculator.getHistory());
//将操作记录保存
caretaker.setMemo(calculator.addMemo());
System.out.println("第三次计算操作:");
calculator.division(200,3);
System.out.println(calculator.getHistory());
//将操作记录保存
caretaker.setMemo(calculator.addMemo());
System.out.println("第四次计算操作:");
calculator.subtract(960,456);
System.out.println(calculator.getHistory());
//将操作记录保存
caretaker.setMemo(calculator.addMemo());
System.out.println("******************第一次回退操作:");
calculator.fallbackMethod(caretaker.getMemoList());
System.out.println(calculator.getHistory());
System.out.println("******************第二次回退操作:");
calculator.fallbackMethod(caretaker.getMemoList());
System.out.println(calculator.getHistory());
System.out.println("******************第三次回退操作:");
calculator.fallbackMethod(caretaker.getMemoList());
System.out.println(calculator.getHistory());
}
}
/**
* @Annotation:发起人--计算器,保存当前记录的数据,并且进行计算业务
* 具有记录历史功能,和查看历史功能
* @Author: yuanzhang
* @Date: 11:19
*/
class Calculator{
private String history;
public float add(float i,float j){
history = i+"+"+j+"="+(i+j);
return i+j;
}
public float subtract(float i,float j){
history = i+"-"+j+"="+(i-j);
return i-j;
}
public float multiply(float i,float j){
history = i+"*"+j+"="+(i*j);
return i*j;
}
public float division(float i,float j){
history = i+"/"+j+"="+(i/j);
return i/j;
}
public String getHistory() {
return history;
}
public Memo addMemo(){
return new Memo(history);
}
public void fallbackMethod(Memo memo){
this.history = memo.getHistory();
}
}
/**
* @Annotation:备忘录--保持计算记录
* @Author: yuanzhang
* @Date: 11:21
*/
class Memo{
private String history;
public Memo(String history) {
this.history = history;
}
public String getHistory() {
return history;
}
public void setHistory(String history) {
this.history = history;
}
}
/**
* @Annotation:管理者--对备忘录进行管理,能添加和获取备忘录
* @Author: yuanzhang
* @Date: 11:22
*/
class Caretaker{
private List<Memo> memoList = new ArrayList <>();
private int index;
public Memo getMemoList() {
return memoList.get(index--);
}
public void setMemo(Memo memo) {
memoList.add(memo);
//不需要记录当前的值
index = memoList.size()-2;
}
}
输出 第一次计算操作: 1.0+2.0=3.0 第二次计算操作: 123.0*321.0=39483.0 第三次计算操作: 200.0/3.0=66.666664 第四次计算操作: 960.0-456.0=504.0 ******************第一次回退操作: 200.0/3.0=66.666664 ******************第二次回退操作: 123.0*321.0=39483.0 ******************第三次回退操作: 1.0+2.0=3.0