`

23种设计模式(17):备忘录模式

 
阅读更多

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

类型:行为类

类图:

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

 

备忘录模式的结构

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

 

通用代码实现

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. class Originator {  
  2.     private String state = "";  
  3.       
  4.     public String getState() {  
  5.         return state;  
  6.     }  
  7.     public void setState(String state) {  
  8.         this.state = state;  
  9.     }  
  10.     public Memento createMemento(){  
  11.         return new Memento(this.state);  
  12.     }  
  13.     public void restoreMemento(Memento memento){  
  14.         this.setState(memento.getState());  
  15.     }  
  16. }  
  17.   
  18. class Memento {  
  19.     private String state = "";  
  20.     public Memento(String state){  
  21.         this.state = state;  
  22.     }  
  23.     public String getState() {  
  24.         return state;  
  25.     }  
  26.     public void setState(String state) {  
  27.         this.state = state;  
  28.     }  
  29. }  
  30. class Caretaker {  
  31.     private Memento memento;  
  32.     public Memento getMemento(){  
  33.         return memento;  
  34.     }  
  35.     public void setMemento(Memento memento){  
  36.         this.memento = memento;  
  37.     }  
  38. }  
  39. public class Client {  
  40.     public static void main(String[] args){  
  41.         Originator originator = new Originator();  
  42.         originator.setState("状态1");  
  43.         System.out.println("初始状态:"+originator.getState());  
  44.         Caretaker caretaker = new Caretaker();  
  45.         caretaker.setMemento(originator.createMemento());  
  46.         originator.setState("状态2");  
  47.         System.out.println("改变后状态:"+originator.getState());  
  48.         originator.restoreMemento(caretaker.getMemento());  
  49.         System.out.println("恢复后状态:"+originator.getState());  
  50.     }  
  51. }  


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

 

多状态多备份备忘录

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

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. class Originator {  
  2.     private String state1 = "";  
  3.     private String state2 = "";  
  4.     private String state3 = "";  
  5.   
  6.     public String getState1() {  
  7.         return state1;  
  8.     }  
  9.     public void setState1(String state1) {  
  10.         this.state1 = state1;  
  11.     }  
  12.     public String getState2() {  
  13.         return state2;  
  14.     }  
  15.     public void setState2(String state2) {  
  16.         this.state2 = state2;  
  17.     }  
  18.     public String getState3() {  
  19.         return state3;  
  20.     }  
  21.     public void setState3(String state3) {  
  22.         this.state3 = state3;  
  23.     }  
  24.     public Memento createMemento(){  
  25.         return new Memento(BeanUtils.backupProp(this));  
  26.     }  
  27.       
  28.     public void restoreMemento(Memento memento){  
  29.         BeanUtils.restoreProp(this, memento.getStateMap());  
  30.     }  
  31.     public String toString(){  
  32.         return "state1="+state1+"state2="+state2+"state3="+state3;  
  33.     }  
  34. }  
  35. class Memento {  
  36.     private Map<String, Object> stateMap;  
  37.       
  38.     public Memento(Map<String, Object> map){  
  39.         this.stateMap = map;  
  40.     }  
  41.   
  42.     public Map<String, Object> getStateMap() {  
  43.         return stateMap;  
  44.     }  
  45.   
  46.     public void setStateMap(Map<String, Object> stateMap) {  
  47.         this.stateMap = stateMap;  
  48.     }  
  49. }  
  50. class BeanUtils {  
  51.     public static Map<String, Object> backupProp(Object bean){  
  52.         Map<String, Object> result = new HashMap<String, Object>();  
  53.         try{  
  54.             BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());  
  55.             PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();  
  56.             for(PropertyDescriptor des: descriptors){  
  57.                 String fieldName = des.getName();  
  58.                 Method getter = des.getReadMethod();  
  59.                 Object fieldValue = getter.invoke(bean, new Object[]{});  
  60.                 if(!fieldName.equalsIgnoreCase("class")){  
  61.                     result.put(fieldName, fieldValue);  
  62.                 }  
  63.             }  
  64.               
  65.         }catch(Exception e){  
  66.             e.printStackTrace();  
  67.         }  
  68.         return result;  
  69.     }  
  70.       
  71.     public static void restoreProp(Object bean, Map<String, Object> propMap){  
  72.         try {  
  73.             BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());  
  74.             PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();  
  75.             for(PropertyDescriptor des: descriptors){  
  76.                 String fieldName = des.getName();  
  77.                 if(propMap.containsKey(fieldName)){  
  78.                     Method setter = des.getWriteMethod();  
  79.                     setter.invoke(bean, new Object[]{propMap.get(fieldName)});  
  80.                 }  
  81.             }  
  82.         } catch (Exception e) {  
  83.             e.printStackTrace();  
  84.         }  
  85.     }  
  86. }  
  87. class Caretaker {  
  88.     private Map<String, Memento> memMap = new HashMap<String, Memento>();  
  89.     public Memento getMemento(String index){  
  90.         return memMap.get(index);  
  91.     }  
  92.       
  93.     public void setMemento(String index, Memento memento){  
  94.         this.memMap.put(index, memento);  
  95.     }  
  96. }  
  97. class Client {  
  98.     public static void main(String[] args){  
  99.         Originator ori = new Originator();  
  100.         Caretaker caretaker = new Caretaker();  
  101.         ori.setState1("中国");  
  102.         ori.setState2("强盛");  
  103.         ori.setState3("繁荣");  
  104.         System.out.println("===初始化状态===\n"+ori);  
  105.           
  106.         caretaker.setMemento("001",ori.createMemento());  
  107.         ori.setState1("软件");  
  108.         ori.setState2("架构");  
  109.         ori.setState3("优秀");  
  110.         System.out.println("===修改后状态===\n"+ori);  
  111.           
  112.         ori.restoreMemento(caretaker.getMemento("001"));  
  113.         System.out.println("===恢复后状态===\n"+ori);  
  114.     }  
  115. }  


 

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

备忘录模式的优点有:

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

备忘录模式的缺点:

  • 在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。

如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如jdbc的事务操作,文本编辑器的Ctrl+Z恢复等。

原文转载于 http://blog.csdn.net/zhengzhb/article/details/7697549

分享到:
评论

相关推荐

    Java描述设计模式(24):备忘录模式.zip

    Java描述设计模式(24):备忘录模式

    设计模式-备忘录模式(讲解及其实现代码)

    备忘录模式是一种在软件工程中广泛使用的面向对象设计模式,它主要用来安全地保存对象的状态,以便在需要时能够恢复到先前的状态。备忘录模式的核心思想是封装对象的状态,将其保存到一个独立的对象(备忘录)中,而...

    设计模式之备忘录(memento)

    设计模式是软件工程中的...总的来说,备忘录模式提供了一种优雅的方式去处理对象状态的保存和恢复,保持了对象的封装性,同时也使得代码更易于维护和扩展。理解并熟练掌握这个模式对于任何开发者来说都是非常有价值的。

    C#面向对象设计模式纵横谈(21):(行为型模式) Memento 备忘录模式

    备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将对象恢复到先前的状态。这种模式在需要撤销/重做功能、...

    备忘录模式.rar备忘录模式.rarjava设计模式

    备忘录模式是一种行为设计模式,它允许在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。这种模式常用于需要记录用户操作历史或者游戏进度...

    设计模式-备忘录

    备忘录模式是一种常用的设计模式,它在软件工程中用于保存对象的状态,以便在需要时恢复到之前的状态。这种模式的主要目标是实现数据的安全存储,同时保持对象的封装性,避免对外部对象直接访问其内部状态。在iOS...

    23种设计模式之备忘录模式

    备忘录模式是一种行为设计模式,它允许在不破坏对象封装性的前提下,保存和恢复对象的状态。在软件开发中,这种模式常用于实现撤销/重做功能或者在需要保存临时状态的情况下。以下是对备忘录模式的详细解释: 1. **...

    Java设计模式-备忘录

    备忘录模式是一种行为设计模式,它允许对象在不破坏封装性的前提下捕获并存储其内部状态,以便稍后恢复到该状态。这种模式常用于在游戏中保存进度、撤销/重做操作、以及在复杂业务逻辑中保存中间计算结果等场景。 ...

    设计模式之备忘录模式

    备忘录模式(Memento Pattern)是软件设计模式中的一种,属于行为模式。它提供了一种方式来恢复对象到之前的状态,即“撤销”操作。备忘录模式的核心思想是保存对象的内部状态,以便在需要时能恢复到这个状态,而...

    java设计模式-备忘录模式源代码

    备忘录模式是一种在软件工程中广泛使用的面向对象设计模式,它主要用来安全地保存对象的状态,以便在需要时能够恢复到先前的状态。这个模式的名字来源于我们日常生活中使用的备忘录,它记录了一些重要的信息,当需要...

    设计模式之备忘录模式,内含可运行代码及详细解释

    备忘录模式是一种常用的设计模式,它在软件工程中扮演着重要的角色,特别是在需要保护对象内部状态不被外部篡改的场景下。备忘录模式的核心思想是提供一种方法来捕获一个对象的内部状态,并在该对象之外保存这个状态...

    第二十二讲:备忘录模式

    备忘录模式是一种设计模式,它允许在不破坏封装性的前提下,捕获并存储一个对象的内部状态,以便在需要时能恢复到该状态。这个模式的核心思想是实现对象状态的保存与恢复,通常用于撤销/重做操作或者游戏存档等功能...

    c#代码介绍23种设计模式-23备忘录模式(附代码)

    个人理解:(利用备忘录对象来保存发起人的内部状态,需要恢复时可以从备忘录对象获取) 1、创建联系人类,作为发起人的内部状态 public class ContactPerson -&gt; public string Name { get; set; } -&gt; public ...

    设计模式之备忘录模式(Memento Pattern)

    备忘录模式(Memento Pattern)是软件设计模式中的一种行为模式,它的主要目的是在不破坏对象封装性的前提下,允许对象在特定时刻保存其内部状态,并能够在之后恢复到保存时的状态。这种模式广泛应用于撤销/重做功能...

    设计模式_备忘录模式.zip

    备忘录模式是一种在软件工程中广泛使用的结构型设计模式,其主要目的是为了在不破坏封装性的前提下,能够安全地保存对象的状态,并在需要时恢复到先前保存的状态。这种模式通常用于那些需要记录和回滚操作的重要场景...

    微信小程序推荐demo:备忘录

    "微信小程序推荐demo:备忘录"是一个示例项目,旨在帮助开发者了解和学习如何利用微信小程序框架开发备忘录类应用。 备忘录小程序通常包含以下几个核心功能模块: 1. **用户界面**:设计简洁易用的用户界面是关键...

    Java 23种设计模式22备忘录模式

    Java 23种设计模式22备忘录模式

    《设计模式:可复用面向对象软件的基础》学习并理解 23 种设计模式

    - **备忘录模式**(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 - **观察者模式**(Observer):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,...

    23种设计模式详解PDF

    设计模式 的分类 总体来说设计模式分为三大类: 创建型模式(5): ...策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    设计模式之备忘录模式的Java版本实现

    备忘录模式是一种在软件设计中广泛使用的结构型设计模式,它的主要目的是为了保存对象的状态,以便在需要的时候能够恢复到之前的状态。备忘录模式的核心思想是通过创建一个备忘录对象来存储原对象的状态,这个备忘录...

Global site tag (gtag.js) - Google Analytics