本文摘自《设计模式就该这样学》1 使用备忘录模式实现草稿框功能大家都用过网页中的富文本编辑器,而编辑器通常自带一个草稿框,可以进行撤消等操作。下面是一段代码来实现这样的功能。假设我们在GPer社区发表一篇文章,文章编辑的过程会比较长,中间还会被撤稿修改,甚至可能需要好几天才能写出一篇高质量的文章,所以可以将编辑好的内容实时保存到草稿箱。首先创建发起者角色编辑器Editor类。公共类编辑器{私人字符串标题;私有字符串内容;私有字符串imgs;publicEditor(Stringtitle,Stringcontent,Stringimgs){this.title=title;this.content=内容;这个.imgs=imgs;}publicStringgetTitle(){返回标题;}publicvoidsetTitle(Stringtitle){this.title=title;}publicStringgetContent(){返回内容;}publicvoidsetContent(Stringcontent){this.content=content;}publicStringgetImgs(){返回图像;}publicvoidsetImgs(Stringimgs){this.imgs=imgs;}publicArticleMementosaveToMemento(){ArticleMementoarticleMemento=newArticleMemento(this.title,this.content,this.imgs);返回文章纪念品;}publicvoidundoFromMemento(ArticleMementoarticleMemento){this.title=articleMemento.getTitle();this.content=articleMemento.get内容();this.imgs=articleMemento.getImgs();}@OverridepublicStringtoString(){return"Editor{"+"title='"+title+'\''+",content='"+content+'\''+",imgs='"+imgs+'\''+'}';}}然后创建备忘录角色ArticleMemento类公共类ArticleMemento{私有字符串标题;私有字符串内容;私有字符串imgs;publicArticleMemento(Stringtitle,Stringcontent,Stringimgs){this.title=title;this.content=内容;这个.imgs=imgs;}publicStringgetTitle(){返回标题;}publicStringgetContent(){返回内容;}publicStringgetImgs(){返回图像;}@OverridepublicStringtoString(){return"ArticleMemento{"+"title='"+title+'\''+",content='"+content+'\''+",imgs='"+imgs+'\''+'}';}}连接着创建备忘记录管理角色草稿箱DraftsBox类。publicclassDraftsBox{privatefinalStackSTACK=newStack();publicArticleMementogetMemento(){ArticleMementoarticleMemento=STACK.pop();返回文章纪念品;}publicvoidaddMemento(ArticleMementoarticleMementoush){(articleMemento);}}草稿箱中定义的Stack类是Vector的子类,实现了标准的后进先出栈。如下表所示,主要定义了以下方法。方法定义方法描述booleanempty()测试栈是否为空Objectpeek()查看栈顶的对象,但不会将其从栈中移除并将其作为此函数的值返回ObjectObjectpush(Objectelement)将对象压入栈顶。intsearch(Objectelement)返回对象在栈中的位置,最后根据1编写客户端测试代码。Editoreditor=newEditor("我就是这样手写Spring的,麻雀虽小,五脏俱全","本文节选自《Spring5核心原理与30个类手写实战》一书,作者:Tom,电子工业出版社。","35576a9ef6fc407aa088eb8280fb1d9d.png");ArticleMementoarticleMemento=editor.saveToMemento();draftsBox.addMemento(articleMemento);System.out.println("Title:"+editor.getTitle()+"\n"+"内容:"+editor.getContent()+"\n"+"图例:"+editor.getImgs()+"\n暂存成功");System.out.println("完整信息"+editor);System.out.println("===========文章第一次修改=============");editor.setTitle([Tom原创]Spring是这样手写的,虽然麻雀小而全");editor.setContent("本文摘自《Spring5核心原理与30个类手写实战》一书,汤姆写的");System.out.println("==========第一个文章修改完成===========");System.out.println("完整信息"+editor);articleMemento=editor.saveToMemento();draftsBox.addMemento(articleMemento);System.out.println("==========保存到草稿箱============");System.out.println("==========第2篇修订=============");editor.setTitle("手写春");editor.setContent("本文节选自《Spring5核心原理与30个类手写实战》一书,作者:Tom");System.out.println("完整信息"+editor);System.out.println("==========文章第二次修改完成==========");System.out.println("==========第一次撤消===========");articleMemento=draftsBox.getMemento();editor.undoFromMemento(articleMemento);System.out.println("完整信息"+editor);System.out.println("==========第一次撤销完成===========");System.out.println("==========第二次撤消===========");articleMemento=draftsBox.getMemento();editor.undoFromMemento(articleMemento);System.out.println("完整信息"+editor);System.out.println("==========2ndundo===========");}运行结果如下图2 备忘录模式应用在Spring源码中,备忘录模式在框架源码中的应用比较少,主要是结合具体的应用场景使用。笔者在JDK源码中查找,至今仍未找到具体的应用,包括MyBatis中相应的源码。在Spring的Webflow源码中还是找到了一个StateManageableMessageContext接口,源码如下。publicinterfaceStateManageableMessageContextextendsMessageContext{publicSerializablecreateMessagesMemento();publicvoidrestoreMessages(SerializablemessagesMemento);publicvoidsetMessageSource(MessageSourcemessageSource);}我们看到有一个创建消息备忘录的createMessagesMemento()方法,可以打开它的实现类,代码如下。公共类DefaultMessageContext实现StateManageableMessageContext{privatestaticfinalLoglogger=LogFactory.getLog(DefaultMessageContext.class);私有消息源消息源;@SuppressWarnings("serial")privateMap