一、备忘录模式定义

1.备忘录模式又称为快照模式或令牌模式,是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态,属于行为型模式

2.在软件系统中,备忘录模式可以为我们提供一种”后悔药“机制,它通过存储系统各个历史状态的快照,使得我们可以在任一时刻将系统回滚到某一个历史状态

3.备忘录模式本质是从发起人实体类隔离存储功能,降低实体类职责。同时由于存储信息独立,且存储信息的实体交由管理类管理,则可以通过为管理类扩展额外的功能对存储信息进行扩展操作

4.备忘录模式的应用场景:

  A.需要保存历史快照的场景

  B.希望在对象之外保存状态,且除了自己其他类对象无法访问状态保存具体内容

二、备忘录模式示例

1.备忘录模式一般包含三种角色:

  A.发起人角色(Originator):负责创建一个备忘录,记录自身需要保存的状态;具备状态回滚功能

  B.备忘录角色(Memento):用于存储Originator的状态,且可以防止Originator以外的对象进行访问

  C.备忘录管理员角色(Caretaker):负责存储、提供管理备忘录,无法对备忘录内容进行操作和访问

2.代码示例

  1 /**
  2  * 发起人角色
  3  */
  4 public class Editor {
  5 
  6     private String title;
  7     private String content;
  8     private String imgs;
  9 
 10     public Editor(String title, String content, String imgs) {
 11         this.title = title;
 12         this.content = content;
 13         this.imgs = imgs;
 14     }
 15 
 16     public String getTitle() {
 17         return title;
 18     }
 19 
 20     public String getContent() {
 21         return content;
 22     }
 23 
 24     public String getImgs() {
 25         return imgs;
 26     }
 27 
 28     public void setTitle(String title) {
 29         this.title = title;
 30     }
 31 
 32     public void setContent(String content) {
 33         this.content = content;
 34     }
 35 
 36     public void setImgs(String imgs) {
 37         this.imgs = imgs;
 38     }
 39 
 40     public ArticleMemento saveToMemento(){
 41         ArticleMemento articleMemento = new ArticleMemento(this.title,this.content,this.imgs);
 42         return articleMemento;
 43     }
 44 
 45     public void undoFromMemento(ArticleMemento articleMemento){
 46         this.title = articleMemento.getTitle();
 47         this.content = articleMemento.getContent();
 48         this.imgs = articleMemento.getImgs();
 49     }
 50 
 51     @Override
 52     public String toString() {
 53         return "Editor{" +
 54                 "title='" + title + '\'' +
 55                 ", content='" + content + '\'' +
 56                 ", imgs='" + imgs + '\'' +
 57                 '}';
 58     }
 59 }
 60 
 61 /**
 62  * 备忘录角色
 63  */
 64 public class ArticleMemento {
 65     private String title;
 66     private String content;
 67     private String imgs;
 68 
 69     public ArticleMemento(String title, String content, String imgs) {
 70         this.title = title;
 71         this.content = content;
 72         this.imgs = imgs;
 73     }
 74 
 75     public String getTitle() {
 76         return title;
 77     }
 78 
 79     public String getContent() {
 80         return content;
 81     }
 82 
 83     public String getImgs() {
 84         return imgs;
 85     }
 86 
 87     @Override
 88     public String toString() {
 89         return "ArticleMemento{" +
 90                 "title='" + title + '\'' +
 91                 ", content='" + content + '\'' +
 92                 ", imgs='" + imgs + '\'' +
 93                 '}';
 94     }
 95 }
 96 
 97 /**
 98  * 备忘录管理角色
 99  */
100 public class DraftsBox {
101     private final Stack<ArticleMemento> STACK = new Stack<ArticleMemento>();
102 
103     public ArticleMemento getMemento(){
104         ArticleMemento articleMemento = STACK.pop();
105         return articleMemento;
106     }
107 
108     public void addMemento(ArticleMemento articleMemento){
109         STACK.push(articleMemento);
110     }
111 
112 }
113 
114 public class Test {
115     public static void main(String[] args) {
116         DraftsBox draftsBox = new DraftsBox();
117 
118         Editor editor = new Editor("我是这样手写Spring的,麻雀虽小五脏俱全",
119                 "本文节选自《Spring5核心原理与30个类手写实战》一书,Tom著,电子工业出版社出版。",
120                 "35576a9ef6fc407aa088eb8280fb1d9d.png");
121 
122         ArticleMemento articleMemento = editor.saveToMemento();
123         draftsBox.addMemento(articleMemento);
124 
125         System.out.println("标题:" + editor.getTitle() + "\n" +
126                             "内容:" + editor.getContent() + "\n" +
127                             "插图:" + editor.getImgs() + "\n暂存成功");
128 
129         System.out.println("完整的信息" + editor);
130 
131 
132         System.out.println("==========首次修改文章===========");
133         editor.setTitle("【Tom原创】我是这样手写Spring的,麻雀虽小五脏俱全");
134         editor.setContent("本文节选自《Spring5核心原理与30个类手写实战》一书,Tom著");
135 
136         System.out.println("==========首次修改文章完成===========");
137 
138         System.out.println("完整的信息" + editor);
139 
140         articleMemento = editor.saveToMemento();
141 
142         draftsBox.addMemento(articleMemento);
143 
144         System.out.println("==========保存到草稿箱===========");
145 
146 
147         System.out.println("==========第2次修改文章===========");
148         editor.setTitle("手写Spring");
149         editor.setContent("本文节选自《Spring5核心原理与30个类手写实战》一书,Tom著");
150         System.out.println("完整的信息" + editor);
151         System.out.println("==========第2次修改文章完成===========");
152 
153         System.out.println("==========第1次撤销===========");
154         articleMemento = draftsBox.getMemento();
155         editor.undoFromMemento(articleMemento);
156         System.out.println("完整的信息" + editor);
157         System.out.println("==========第1次撤销完成===========");
158 
159 
160         System.out.println("==========第2次撤销===========");
161         articleMemento = draftsBox.getMemento();
162         editor.undoFromMemento(articleMemento);
163         System.out.println("完整的信息" + editor);
164         System.out.println("==========第2次撤销完成===========");
165 
166     }
167 }

3.备忘录模式优缺点

  A.优点

    a.简化发起人实体类职责,隔离状态存储与获取,实现了信息的封装,客户端无需关心状态的保存细节

    b.提供状态回滚功能

  B.缺点

    a.消耗资源:如果需要保存的状态过多,每一次保存都会消耗很多内存