• 备忘录模式


    备忘录模式,望文生义就知道它是用来做备忘的,或者可以直接说是“备份”。当需要保存当前状态,以便在不久要恢复此状态时,就可以使用“备忘录模式”。将当前”状态“备份,是不是又new一个类,然后将每个字段方法copy过去就可以了呢?或者说使用我们之前clone方法做深复制浅复制呢?其实不然,在《大话设计模式》中,作者提到了原因,这样会暴露更多的细节给客户端,不符合我们面向对象的思想。什么是暴露更多的细节给客户端?我们来看下面一段代码。

     1 package day_27_memento;
     2 
     3 /**
     4  * @author turbo
     5  *
     6  * 2016年9月27日
     7  */
     8 public class Client {
     9 
    10     /**
    11      * @param args
    12      */
    13     public static void main(String[] args) {
    14         /*状态一*/
    15         Test nowTest = new Test();
    16         nowTest.setField("状态一");
    17         
    18         /*备份状态*/
    19         Test backUpTest = new Test();
    20         backUpTest.setField(nowTest.getField());
    21         
    22         /*修改状态一*/
    23         nowTest.setField("修改状态一,改为状态二");
    24         
    25         /*还原状态*/
    26         nowTest.setField(backUpTest.getField());
    27     }
    28 
    29 }

    Test类中只有一个field字段,不再贴出代码。由上代码我们可以看到,如果要备份的字段较多,在客户端里就会暴露过多的细节。而我们希望的是,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这句话的后面两句是啥意思呢?捕获一个对象的内部状态——值得是要获得需要备份的状态(或者简单理解为字段),该备份状态要保存在另外一个类并要有对象自己来读取。

    我们还是先来看代码。在备忘录模式中涉及到三个基本的类,一个是原始类,即需要备份的状态类,一个是备份类,即具体存储状态,还有一个管理者,用来提供备份状态类。

    首先实现原始类,在这个类里除去该类本身自有的方法,还要有一个创建备份和获取备份的两个方法。

     1 package day_27_memento;
     2 
     3 /**
     4  * 发起人,它要负责创建一个备忘录Memento用来记录当前时刻它的状态
     5  * @author turbo
     6  *
     7  * 2016年9月27日
     8  */
     9 public class Originator {
    10     private String state;
    11 
    12     public String getState() {
    13         return state;
    14     }
    15 
    16     public void setState(String state) {
    17         this.state = state;
    18     }
    19     
    20     /**
    21      * 显示状态
    22      */
    23     public void show(){
    24         System.out.println("state : " + state);
    25     }
    26     
    27     /**
    28      * 创建备忘录
    29      * @return 备份的状态
    30      */
    31     public Memento createMemento(){
    32         return (new Memento(state));  //在这句我们可以看到将状态细节封装在了内部,对外部透明。
    33     }
    34     
    35     /**
    36      * 获取备份
    37      * @param memento 备份类
    38      */
    39     public void setMememto(Memento memento){
    40         state = memento.getState();
    41     }
    42 }

    备忘类。

     1 package day_27_memento;
     2 
     3 /**
     4  * 备忘类
     5  * @author turbo
     6  *
     7  * 2016年9月27日
     8  */
     9 public class Memento {
    10     private String state;
    11     
    12     public String getState() {
    13         return state;
    14     }
    15 
    16     public Memento(String state){
    17         this.state = state;
    18     }
    19 }

    接着来看看这个管理者类。

     1 package day_27_memento;
     2 
     3 /**
     4  * 管理者
     5  * @author turbo
     6  *
     7  * 2016年9月27日
     8  */
     9 public class Caretaker {
    10     private Memento memento;
    11 
    12     public Memento getMemento() {
    13         return memento;
    14     }
    15 
    16     public void setMemento(Memento memento) {
    17         this.memento = memento;
    18     }
    19     
    20 }

    管理者类就是用来提供备忘录类的。最后我们来看客户端代码。

     1 package day_27_memento;
     2 
     3 /**
     4  * @author turbo
     5  *
     6  * 2016年9月27日
     7  */
     8 public class Main {
     9     public static void main(String[] args){
    10         /*当前状态*/
    11         Originator originator = new Originator();
    12         originator.setState("On");
    13         originator.show();
    14         /*备份当前状态*/
    15         Caretaker caretaker = new Caretaker();
    16         caretaker.setMemento(originator.createMemento());
    17         /*更新状态*/
    18         originator.setState("Off");
    19         originator.show();
    20         /*备份状态*/
    21         originator.setMememto(caretaker.getMemento());
    22         originator.show();
    23     }
    24 }

    从代码16行、21行,我们能看到实际上就是书中所说,“有时一些对象的内部信息必须保存在对象以外的地方,但是必须要由对象自己读取”。

  • 相关阅读:
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(88)-Excel导入和导出-主从表结构导出
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(89)-EF执行SQL语句与存储过程
    ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试
    ASP.NET MVC5+EF6+EasyUI 仓库管理系统
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(91)-EF 连接 MySql
    样例功能截图
    Fastreport.net 如何在开发MVC应用程序时使用报表
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(90)-EF 扩展操作
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(86)-日程管理-fullcalendar插件用法
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/5914814.html
Copyright © 2020-2023  润新知