当前位置:首页 > java技术文章 > 23种设计模式(18)java备忘录模式

java备忘录模式

  • 发布时间:
  • 作者:码农之家原创
  • 点击:81

这篇文章主要知识点是关于java、备忘录模式、的内容,如果大家想对相关知识点有系统深入的学习,可以参阅以下电子书

Java函数式编程
Java函数式编程中文扫描版
  • 类型:Java编程大小:205.8 MB格式:PDF作者:Pierre-Yves
立即下载

23种设计模式(18)java备忘录模式

23种设计模式第十八篇:java备忘录模式

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。

类型:行为类

类图:

23种设计模式(18)java备忘录模式

我们在编程的时候,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态。比如,我们使用Eclipse进行编程时,假如编写失误(例如不小心误删除了几行代码),我们希望返回删除前的状态,便可以使用Ctrl+Z来进行返回。这时我们便可以使用备忘录模式来实现。

备忘录模式的结构

发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
管理角色:对备忘录进行管理,保存和提供备忘录。

通用代码实现

 

class Originator { 
    private String state = ""; 
     
    public String getState() { 
      return state; 
    } 
    public void setState(String state) { 
      this.state = state; 
    } 
    public Memento createMemento(){ 
      return new Memento(this.state); 
    } 
    public void restoreMemento(Memento memento){ 
      this.setState(memento.getState()); 
    } 
  } 
   
  class Memento { 
    private String state = ""; 
    public Memento(String state){ 
      this.state = state; 
    } 
    public String getState() { 
      return state; 
    } 
    public void setState(String state) { 
      this.state = state; 
    } 
  } 
  class Caretaker { 
    private Memento memento; 
    public Memento getMemento(){ 
      return memento; 
    } 
    public void setMemento(Memento memento){ 
      this.memento = memento; 
    } 
  } 
  public class Client { 
    public static void main(String[] args){ 
      Originator originator = new Originator(); 
      originator.setState("状态1"); 
      System.out.println("初始状态:"+originator.getState()); 
      Caretaker caretaker = new Caretaker(); 
      caretaker.setMemento(originator.createMemento()); 
      originator.setState("状态2"); 
      System.out.println("改变后状态:"+originator.getState()); 
      originator.restoreMemento(caretaker.getMemento()); 
      System.out.println("恢复后状态:"+originator.getState()); 
    } 
  }

        代码演示了一个单状态单备份的例子,逻辑非常简单:Originator类中的state变量需要备份,以便在需要的时候恢复;Memento类中,也有一个state变量,用来存储Originator类中state变量的临时状态;而Caretaker类就是用来管理备忘录类的,用来向备忘录对象中写入状态或者取回状态。

多状态多备份备忘录

       通用代码演示的例子中,Originator类只有一个state变量需要备份,而通常情况下,发起人角色通常是一个javaBean,对象中需要备份的变量不止一个,需要备份的状态也不止一个,这就是多状态多备份备忘录。
        实现备忘录的方法很多,备忘录模式有很多变形和处理方式,像通用代码那样的方式一般不会用到,多数情况下的备忘录模式,是多状态多备份的。其实实现多状态多备份也很简单,最常用的方法是,我们在Memento中增加一个Map容器来存储所有的状态,在Caretaker类中同样使用一个Map容器才存储所有的备份。下面我们给出一个多状态多备份的例子:

class Originator { 
    private String state1 = ""; 
    private String state2 = ""; 
    private String state3 = ""; 
   
    public String getState1() { 
      return state1; 
    } 
    public void setState1(String state1) { 
      this.state1 = state1; 
    } 
    public String getState2() { 
      return state2; 
    } 
    public void setState2(String state2) { 
      this.state2 = state2; 
    } 
    public String getState3() { 
      return state3; 
    } 
    public void setState3(String state3) { 
      this.state3 = state3; 
    } 
    public Memento createMemento(){ 
      return new Memento(BeanUtils.backupProp(this)); 
    } 
     
    public void restoreMemento(Memento memento){ 
      BeanUtils.restoreProp(this, memento.getStateMap()); 
    } 
    public String toString(){ 
      return "state1="+state1+"state2="+state2+"state3="+state3; 
    } 
  } 
  class Memento { 
    private Map<String, Object> stateMap; 
     
    public Memento(Map<String, Object> map){ 
      this.stateMap = map; 
    } 
   
    public Map<String, Object> getStateMap() { 
      return stateMap; 
    } 
   
    public void setStateMap(Map<String, Object> stateMap) { 
      this.stateMap = stateMap; 
    } 
  } 
  class BeanUtils { 
    public static Map<String, Object> backupProp(Object bean){ 
      Map<String, Object> result = new HashMap<String, Object>(); 
      try{ 
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); 
        PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); 
        for(PropertyDescriptor des: descriptors){ 
          String fieldName = des.getName(); 
          Method getter = des.getReadMethod(); 
          Object fieldValue = getter.invoke(bean, new Object[]{}); 
          if(!fieldName.equalsIgnoreCase("class")){ 
            result.put(fieldName, fieldValue); 
          } 
        } 
         
      }catch(Exception e){ 
        e.printStackTrace(); 
      } 
      return result; 
    } 
     
    public static void restoreProp(Object bean, Map<String, Object> propMap){ 
      try { 
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); 
        PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); 
        for(PropertyDescriptor des: descriptors){ 
          String fieldName = des.getName(); 
          if(propMap.containsKey(fieldName)){ 
            Method setter = des.getWriteMethod(); 
            setter.invoke(bean, new Object[]{propMap.get(fieldName)}); 
          } 
        } 
      } catch (Exception e) { 
        e.printStackTrace(); 
      } 
    } 
  } 
  class Caretaker { 
    private Map<String, Memento> memMap = new HashMap<String, Memento>(); 
    public Memento getMemento(String index){ 
      return memMap.get(index); 
    } 
     
    public void setMemento(String index, Memento memento){ 
      this.memMap.put(index, memento); 
    } 
  } 
  class Client { 
    public static void main(String[] args){ 
      Originator ori = new Originator(); 
      Caretaker caretaker = new Caretaker(); 
      ori.setState1("中国"); 
      ori.setState2("强盛"); 
      ori.setState3("繁荣"); 
      System.out.println("===初始化状态===\n"+ori); 
       
      caretaker.setMemento("001",ori.createMemento()); 
      ori.setState1("软件"); 
      ori.setState2("架构"); 
      ori.setState3("优秀"); 
      System.out.println("===修改后状态===\n"+ori); 
       
      ori.restoreMemento(caretaker.getMemento("001")); 
      System.out.println("===恢复后状态===\n"+ori); 
    } 
  }

备忘录模式的优缺点和适用场景

备忘录模式的优点有:

        当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。
        备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。

备忘录模式的缺点有:

        在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。
        如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如jdbc的事务操作,文本编辑器的Ctrl+Z恢复等。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。

以上就是本次给大家分享的关于java的全部知识点内容总结,大家还可以在下方相关文章里找到相关文章进一步学习,感谢大家的阅读和支持。

推荐内容

Java中抽象类的使用及其与注意事项

实例解析Yii2框架整合Xunsearch搜索引擎的方法

ipython和python区别点总结

python爬虫实现校园网自动重连脚本的方法

jQuery Ajax数据加载知识点总结

展开 +

收起 -

Java 相关电子书
学习笔记
网友NO.376114

Java继承概念知识点分享

继承与合成基本概念 继承:可以基于已经存在的类构造一个新类。继承已经存在的类就可以复用这些类的方法和域。在此基础上,可以添加新的方法和域,从而扩充了类的功能。 合成:在新类里创建原有的对象称为合成。这种方式可以重复利用现有的代码而不更改它的形式。 1.继承的语法 关键字extends表明新类派生于一个已经存在的类。已存在的类称为父类或基类,新类称为子类或派生类。例如: class Student extends Person {} 类Student继承了Person,Person类称为父类或基类,Student类称为子类或派生类。 2.合成的语法 合成比较简单,就是在一个类中创建一个已经存在的类。 class Student { Dog dog;} 上溯造型 1.基本概念 继承的作用在于代码的复用。由于继承意味着父类的所有方法亦可在子类中使用,所以发给父类的消息亦可发给衍生类。如果Person类中有一个eat方法……

网友NO.766007

java实现单机版五子棋

这个小游戏是我和我姐们儿的JAVA课程设计,也是我做的第一个JAVA项目,适合初学者,希望能帮到那些被JAVA课设所困扰的孩纸们~~~ 一、该游戏需要实现 1、设计主框架,界面。 2、利用ActionListener接口实现按钮事件的监听。 3、重新开始功能的实现。 4、悔棋功能的实现。 5、退出功能的实现。 6、棋盘中棋子点类的定义。 7、利用MouseListener接口实现事件监听,并实现接口里的所有方法。 8、当鼠标移动到棋盘上的交点上,且该点上无棋子时能够变成小手形状。 9、点击棋盘时,利用if语句判断该点是否点在交点上,并利用foreach语句和棋子类中的getX(),getY()方法遍历每一个棋子的位置判断该点是否有棋子。 10、当判断到可以在所点击的点上下子时,画棋子时利用for循环遍历已有的每一个点并利用Graphics类的setColor设置颜色,利用Graphics类的fillOval方法设……

网友NO.227844

JavaScript实现星级评价效果

本文实例为大家分享了js实现星级评价效果展示的具体代码,供大家参考,具体内容如下 背景图片实现 图片是 width:36px; height:25px; 背景是白色,中间一个空的五角星,空的边缘有一像素的边框;(不然就看不到了); !DOCTYPE htmlhtml lang="en"head meta charset="UTF-8" title星级评价(可半星)/title style .xin{height: 25px; background: url(images/x.png); position: relative; display: inline-block;} .xin span{display: block; height: 25px; background: #f60; position: absolute; left: 0; top: 0;z-index: -1;transition: 0.2s;} .xin ul{position: absolute; top: 0; left: 0; height: 25px; margin: 0; padding: 0; list-style: none;} .xin ul li{float: left; width: 18px; height: 25px;} .fensu{display: inline-block;} /style/headbody input type="hidden" title="10" value="3.5" input type="hidden" title="5" value="1.5" script var input=document.querySelectorAll("input[type=hidden]"); input.forEach(function(_input){ var Div=document.c……

网友NO.430624

Java实现简单日历小程序 Java图形界面小日历开发

今天给大家介绍一下如何用Java swing开发一款简单的小日历,下面我们来看代码: 首先创建一个CalendarBean类,用于基本的日期计算: package other1; import java.util.Calendar; public class CalendarBean { String day[]; int year=2005,month=0; public void setYear(int year) { this.year=year; } public int getYear() { return year; } public void setMonth(int month) { this.month=month; } public int getMonth() { return month; } public String[] getCalendar() { String a[]=new String[42]; Calendar date=Calendar.getInstance(); date.set(year,month-1,1); int week=date.get(Calendar.DAY_OF_WEEK)-1; int day=0; //判断大月份 if(month==1||month==3||month==5||month==7 ||month==8||month==10||month==12) { day=31; } //判断小月 if(month==4||month==6||month==9||month==11) { day=30; } //判断平年与闰年 if(month==2) { if(((year%4==0)(year%100!=0))||(year%400==0)) { day=29; } else { day=28; } } for(int i=week,n=1;iweek+day;i++) { a[i]=String.valueOf(n) ; n++; ……

网友NO.606669

javascript获取以及设置光标位置

一. 获取光标位置: // 获取光标位置function getCursortPosition (textDom) { var cursorPos = 0; if (document.selection) { // IE Support textDom.focus (); var selectRange = document.selection.createRange(); selectRange.moveStart ('character', -textDom.value.length); cursorPos = selectRange.text.length; }else if (textDom.selectionStart || textDom.selectionStart == '0') { // Firefox support cursorPos = textDom.selectionStart; } return cursorPos;} 二. 设置光标位置: // 设置光标位置function setCaretPosition(textDom, pos){ if(textDom.setSelectionRange) { // IE Support textDom.focus(); textDom.setSelectionRange(pos, pos); }else if (textDom.createTextRange) { // Firefox support var range = textDom.createTextRange(); range.collapse(true); range.moveEnd('character', pos); range.moveStart('character', pos); range.select(); }} 三. 获取选中文字: // 获取选中文字function getSelectText() { var userSelection, text; if (window.getSelection) { // Firefox support us……

<
1
>

电子书 编程教程 文档 软件 源码 视频

Copyright 2018-2020 xz577.com 码农之家

本站所有电子书资源不再提供下载地址,只分享来路

免责声明:网站所有作品均由会员网上搜集共同更新,仅供读者预览及学习交流使用,下载后请24小时内删除

版权投诉 / 书籍推广 / 赞助:QQ:520161757