备忘录模式

定义

保存一个对象的某个状态,以便在适当的时候恢复对象。这里的状态可以理解为对象的一个快照。

类型

行为型

适用场景

1
2
1 保存及恢复数据相关业务场景
2 后悔的时候,即想恢复到之前的状态

优点

1
2
1 为用户提供一种可恢复机制
2 存档信息的封装

缺点

1
2
资源占用
- 如果暂存的对象比较多,而且对象的属性也比较多,那么肯定会对资源造成一定的消耗,占用大量的资源。

相关的设计模式

备忘录模式和状态模式

1
备忘录模式中是用实例来表示状态的,我们存档的是一个对象实例。状态模式中是使用类来表示状态。

简单需求

在写文档时,间断性地保存,然后可以撤销回退到上一个版本

备忘录模式演练

文章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.design.pattern.memento;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

/**
* Article 文章
*
* @author shunhua
* @date 2019-10-04
*/
@Data
@AllArgsConstructor
public class Article implements Serializable {

private static final long serialVersionUID = -321234774998152556L;

/**
* 文章标题
*/
private String title;
/**
* 文章内容
*/
private String content;
/**
* 图片
*/
private String img;

/**
* 把文章保存起来
* @return
*/
public ArticleMemento saveToMemento(){
ArticleMemento articleMemento = new ArticleMemento(this.title,this.content,this.img);
return articleMemento;
}

/**
* 把保存的文章标题、内容以及图片回退回来
* @param articleMemento
*/
public void undoFromMemento(ArticleMemento articleMemento){
this.title = articleMemento.getTitle();
this.content = articleMemento.getContent();
this.img = articleMemento.getImg();
}

}

文章快照

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.design.pattern.memento;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

/**
* ArticleMemento 文章快照,对于快照不需要Setter方法,只用于保存
*
* @author shunhua
* @date 2019-10-04
*/
@Getter
@ToString
@AllArgsConstructor
public class ArticleMemento {
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 图片
*/
private String img;

}

文章快照暂存管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.design.pattern.memento;

import java.util.Stack;

/**
* ArticleMementoManager 文章快照管理者
*
* @author shunhua
* @date 2019-10-04
*/
public class ArticleMementoManager {

/**
* 保存 文章快照 的栈,在回退的时候回退的是最新的状态
*/
private final Stack<ArticleMemento> ARTICLE_MEMENTO_STACK = new Stack<>();

/**
* 获取文章快照
* @return
*/
public ArticleMemento getMemento(){
ArticleMemento articleMemento = ARTICLE_MEMENTO_STACK.pop();
return articleMemento;
}

/**
* 把文章保存为快照
* @param articleMemento
*/
public void addMemento(ArticleMemento articleMemento){
ARTICLE_MEMENTO_STACK.push(articleMemento);
}
}

备忘录模式在源码中的使用

spring-webflow中的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

package org.springframework.binding.message;

import java.io.Serializable;

import org.springframework.context.MessageSource;

/**
* A message context whose internal state can be managed by an external care-taker. State management employs the GOF
* Memento pattern. This context can produce a serializable memento representing its internal state at any time. A
* care-taker can then use that memento at a later time to restore any context instance to a previous state.
*
* @author Keith Donald
*/
public interface StateManageableMessageContext extends MessageContext {

/**
* 存档
* Create a serializable memento, or token representing a snapshot of the internal state of this message context.
* @return the messages memento
*/
Serializable createMessagesMemento();

/**
* 回退
* Set the state of this context from the memento provided. After this call, the messages in this context will match
* what is encapsulated inside the memento. Any previous state will be overridden.
* @param messagesMemento the messages memento
*/
void restoreMessages(Serializable messagesMemento);

/**
* Configure the message source used to resolve messages added to this context. May be set at any time to change how
* coded messages are resolved.
* @param messageSource the message source
* @see MessageContext#addMessage(MessageResolver)
*/
void setMessageSource(MessageSource messageSource);
}