应用场景:需要保存对象的状态和值。
1. 简介

public interface Memento {
}public class Originator {//表示原发器的状态 private String state = "";public Memento createMemento() {//创建保存原发器对象的状态的备忘录对象 return new MementoImpl(state);}//重新设置原发器对象的状态,让其回到备忘录对象记录的状态 public void setMemento(Memento memento) {MementoImpl mementoImpl = (MementoImpl)memento;this.state = mementoImpl.getState();}//真正的备忘录对象,实现备忘录窄接口 private static class MementoImpl implements Memento{ private String state = "";public MementoImpl(String state){this.state = state;}public String getState() {return state;}}
}public class Caretaker{ private Memento memento = null; public void saveMemento(Memento memento){this.memento = memento;} public Memento retriveMemento(){return this.memento;}
}

2. 应用到场景

2.1. 创建备忘录

2.2. 从备忘录恢复

public interface FlowAMockMemento extends Serializable{
}public class FlowAMementoCareTaker {//记录被保存的备忘录对象 private FlowAMockMemento memento = null;//保存备忘录对象 public void saveMemento(FlowAMockMemento memento){this.memento = memento;}// 获取被保存的备忘录对象 public FlowAMockMemento retriveMemento(){return this.memento;}
}public class FlowAMementoFileCareTaker { //保存备忘录对象 public void saveMemento(FlowAMockMemento memento){//写到文件中ObjectOutputStream out = null;try{out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("FlowAMemento")));out.writeObject(memento);...  }//获取被保存的备忘录对象 public FlowAMockMemento retriveMemento(){FlowAMockMemento memento = null;//从文件中获取备忘录数据ObjectInputStream in = null;try{in = new ObjectInputStream(new BufferedInputStream(new FileInputStream("FlowAMemento")));memento = (FlowAMockMemento)in.readObject();...return memento;}
}public class FlowAMock implements Serializable {//流程名称,不需要外部存储的状态数据 private String flowName; //示意,代指某个中间结果,需要外部存储的状态数据 private int tempResult; //示意,代指某个中间结果,需要外部存储的状态数据 private String tempState; //构造方法,传入流程名称 public FlowAMock(String flowName){this.flowName = flowName;}//示意,运行流程的第一个阶段 public void runPhaseOne(){//在这个阶段,可能产生了中间结果,示意一下tempResult = 3;tempState = "PhaseOne";}//示意,按照方案一来运行流程后半部分 public void schema1(){ this.tempState += ",Schema1";//示意,需要使用第一个阶段产生的数据System.out.println(this.tempState + " : now run "+tempResult);this.tempResult += 11;} public void schema2(){ }  //创建保存原发器对象的状态的备忘录对象 public FlowAMockMemento createMemento() {return new MementoImpl(this.tempResult,this.tempState);}//重新设置原发器对象的状态,让其回到备忘录对象记录的状态 public void setMemento(FlowAMockMemento memento) {MementoImpl mementoImpl = (MementoImpl)memento;this.tempResult = mementoImpl.getTempResult();this.tempState = mementoImpl.getTempState();}//真正的备忘录对象,实现备忘录窄接口 private static class MementoImpl implements FlowAMockMemento{ private int tempResult;//示意,保存某个中间结果  private String tempState;//示意,保存某个中间结果public MementoImpl(int tempResult,String tempState){this.tempResult = tempResult;this.tempState = tempState;}public int getTempResult() {return tempResult;}public String getTempState() {return tempState;}}
}public class FlowAMockPrototype implements Cloneable { private String flowName; private int tempResult;//示意,代指某个中间结果,需要外部存储的状态数据 private String tempState;public FlowAMockPrototype(String flowName){this.flowName = flowName;}//示意,运行流程的第一个阶段 public void runPhaseOne(){//在这个阶段,可能产生了中间结果,示意一下tempResult = 3;tempState = "PhaseOne";}//示意,按照方案一来运行流程后半部分 public void schema1(){//示意,需要使用第一个阶段产生的数据 } public void schema2(){ }    //创建保存原发器对象的状态的备忘录对象 public FlowAMockMemento createMemento() { return new MementoImplPrototype((FlowAMockPrototype) this.clone()); } //重新设置原发器对象的状态,让其回到备忘录对象记录的状态 public void setMemento(FlowAMockMemento memento) {MementoImplPrototype mementoImpl = (MementoImplPrototype)memento;this.tempResult = mementoImpl.getFlowAMock().tempResult;this.tempState = mementoImpl.getFlowAMock().tempState;}//真正的备忘录对象,实现备忘录窄接口,// 实现成私有的内部类,不让外部访问 private static class MementoImplPrototype implements FlowAMockMemento{private FlowAMockPrototype flowAMock = null; public MementoImplPrototype(FlowAMockPrototype f){this.flowAMock = f;} public FlowAMockPrototype getFlowAMock() {return flowAMock;}}
}public static void main(String[] args) {// 创建模拟运行流程的对象FlowAMock mock = new FlowAMock("TestFlow");//运行流程的第一个阶段mock.runPhaseOne();//创建一个管理者FlowAMementoCareTaker careTaker = new FlowAMementoCareTaker();//创建此时对象的备忘录对象,并保存到管理者对象那里,后面要用FlowAMockMemento memento = mock.createMemento();careTaker.saveMemento(memento);//按照方案一来运行流程后半部分mock.schema1();//从管理者获取备忘录对象,然后设置回去,//让模拟运行流程的对象自己恢复自己的内部状态mock.setMemento(careTaker.retriveMemento());//按照方案二来运行流程后半部分mock.schema2();}

3. redo/undo借助备忘录模式

// todo

4. 总结

备忘录模式的本质:保存和恢复内部状态

  • 如果必须保存一个对象在某一个时刻的全部或者部分状态,方便在以后需要的时候把该对象恢复到先前的状态,可以使用备忘录模式。

  • 使用备忘录对象来封装和保存需要保存的内部状态,然后把备忘录对象保存到管理者对象中,在需要的时候,再从管理者对象中获取备忘录对象,来恢复对象的状态。

  • 如果需要保存一个对象的内部状态,但是如果用接口来让其他对象直接得到这些需要保存的状态,将会暴露对象的实现细节并破坏对象的封装性,这时可以使用备忘录模式,把备忘录对象实现成为原发器对象的内部类,而且还是私有的,从而保证只有原发器对象才能访问该备忘录对象。这样既保存了需要保存的状态,又不会暴露原发器对象的内部实现细节。

《研磨设计模式》chap19 备忘录模式相关推荐

  1. java备忘录模式应用场景_图解Java设计模式之备忘录模式

    图解Java设计模式之备忘录模式 游戏角色状态恢复问题 游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态. ...

  2. 研磨设计模式之 策略模式--转

    http://www.uml.org.cn/sjms/201009092.asp 研磨设计模式之 策略模式   2010-09-09 作者:云飞龙行 来源:云飞龙行的blog   先感谢众多朋友的支持 ...

  3. java之备忘录模式,java设计模式之备忘录模式

    java设计模式之备忘录模式 代码无错便是优? 简介: 在不破坏封装性的前提下 , 捕获一个对象的内部状态,并在该对象之外保存这个状态 , 这样以后就可以将该对象恢复到原先保存的状态 . 备忘录模式就 ...

  4. Alamps学习设计模式之备忘录模式(笑话:劫个色OR抢个鸡蛋版)

    //设计模式之备忘录模式(月光宝盒版),只要喊菠萝菠萝蜜,就能返回事件的原点.//至尊宝//爱你一万年 class LoverWords {// 模拟Memento     private Strin ...

  5. 设计模式之备忘录模式 转载

    https://juejin.im/post/59c8eb6951882564c5164c5f 设计模式之备忘录模式 备忘录模式 介绍 是一种行为模式 用于保存对象当前状态,并在之后恢复到此状态(后悔 ...

  6. java备忘录模式 类图,Android编程设计模式之备忘录模式详解

    本文实例讲述了Android编程设计模式之备忘录模式.分享给大家供大家参考,具体如下: 一.介绍 备忘录模式是一种行为模式,该模式用于保存对象当前状态,并且在之后可以再次恢复到此状态,这有点像我们平时 ...

  7. 研磨设计模式之外观模式(Facade)(解决方案)

    3.2  解决方案 3.2.1  外观模式来解决 用来解决上述问题的一个合理的解决方案就是外观模式.那么什么是外观模式呢? (1)外观模式定义 这里先对两个词进行一下说明,一个是界面,一个是接口. 界 ...

  8. 设计模式之备忘录模式(Memento)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  9. 设计模式复习-备忘录模式

    #pragma once #include "stdafx.h" #include<string> #include<iostream> using nam ...

最新文章

  1. 万万没想到,逛B站也能学编程了
  2. CTF(pwn) 堆利用 之 unlink 介绍
  3. 【问链财经-区块链基础知识系列】 第二十六课 隐私保护方法:多方安全计算和区块链
  4. SpringMVC使用AOP
  5. 大剑无锋之简单说一下聚簇索引和非聚簇索引?【面试推荐】
  6. C# 外接(网口)双摄像头视频获取
  7. [html] 如何让pre标签中的元素自动换行?
  8. 在CentOS 6上搭建LNMP环境
  9. go socket编程(详细)
  10. 【C++ Primer】 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
  11. 企业生产一线管理应找怎样的好帮手?
  12. 视频矩阵的作用及原理
  13. 设置div显示隐藏的N种方法
  14. 【Rust日报】 2019-01-26
  15. 西湖大学正式开学! 120名博士新生入校,每月补助5000多元
  16. java ODBC连接MYSQL数据库
  17. DataFrame的元素选择与赋值
  18. 【利用Altium Designer2018设计元器件原理图库】
  19. db block gets、consistent gets和physical reads
  20. 周末玩OPENWRT--多WAN PPTP

热门文章

  1. Android --- 解决 cannot connect to daemon at tcp:5037: cannot connect to 127.0.0.1:5037: 由于目标计算机积极拒绝,无
  2. Java 洛谷 P1014 Cantor表
  3. 残缺棋盘的伪代码_伪激光雷达:无人驾驶的立体视觉
  4. ubuntu19 安装git_如何在Ubuntu 20.04上安装Git
  5. zabbix mysql主从延迟_zabbix监控mysql主从同步和延迟
  6. 数据中心建设提速 2021年呈四大发展趋势
  7. 中国首个海底数据中心样机测试数据揭晓,达世界先进能效水平
  8. DataScience:深入探讨与分析机器学习中的数据处理之非线性变换—log对数变换、sigmoid/softmax变换
  9. Interview:算法岗位面试—10.10下午—上海某银行算法岗位(偏数据分析,四大行之一)的技术面—关于项目的考察
  10. Keras之MLPR:利用MLPR算法(1to1+【Input(1)→8(relu)→O(mse)】)实现根据历史航空旅客数量数据集(时间序列数据)预测下月乘客数量问题