# 备忘录模式Memento

loading

# 一、概念

# 1、定义

保存一个对象的某个状态,以便在适当的时候恢复对象。

# 2、补充

“后悔药”

# 3、类型

行为型

# 4、适用场景

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

# 5、优点

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

# 6、缺点

资源占用

# 7、相关设计模式

  • 备忘录模式和状态模式

备忘录模式是用实例表示状态,存的存档是一个对象的实例;状态模式是用类表示状态。

# 二、应用

首先创建一个笔记类:

public class Article {

    private String title;
    private String content;
    private String image;

    public Article(String title, String content, String image) {
        this.title = title;
        this.content = content;
        this.image = image;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public ArticleMemento saveToMemento() {
        ArticleMemento articleMemento = new ArticleMemento(title, content, image);
        return articleMemento;
    }

    public void undoFromMemento(ArticleMemento articleMemento) {
        this.title = articleMemento.getTitle();
        this.content = articleMemento.getContent();
        this.image = articleMemento.getImage();
    }

    @Override
    public String toString() {
        return "Article{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", image='" + image + '\'' +
                '}';
    }
}
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
53
54
55
56

其中 saveToMemento() 就是保存笔记的方法,undoFromMemento() 就是还原的方法。

看下 ArticleMemento 类:

public class ArticleMemento {

    private String title;
    private String content;
    private String image;

    public ArticleMemento(String title, String content, String image) {
        this.title = title;
        this.content = content;
        this.image = image;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public String getImage() {
        return image;
    }

    @Override
    public String toString() {
        return "ArticleMemento{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", image='" + image + '\'' +
                '}';
    }
}
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

在看下 ArticleMementoManager 的管理类:

public class ArticleMementoManager {

    private final Stack<ArticleMemento> ARTICLE_MEMENTO_STACK = new Stack<>();

    public ArticleMemento getMemento() {
        return ARTICLE_MEMENTO_STACK.pop();
    }

    public void addMemento(ArticleMemento articleMemento) {
        ARTICLE_MEMENTO_STACK.push(articleMemento);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

类图:

备忘录模式

测试类:

public class Test {

    public static void main(String[] args) {
        ArticleMementoManager articleMementoManager = new ArticleMementoManager();
        Article article = new Article("Java设计模式A", "内容A", "图片A");
        ArticleMemento articleMemento = article.saveToMemento();

        // 存档
        articleMementoManager.addMemento(articleMemento);
        System.out.println("原始:" + article);

        System.out.println("修改笔记 start");
        article.setTitle("Java设计模式B");
        article.setContent("内容B");
        article.setImage("图片B");
        System.out.println("修改笔记 end");

        System.out.println("修改1次后:" + article);

        articleMemento = article.saveToMemento();
        articleMementoManager.addMemento(articleMemento);

        article.setTitle("Java设计模式C");
        article.setContent("内容C");
        article.setImage("图片C");
        System.out.println("修改2次后:" + article);

        System.out.println("暂存回退 start");
        System.out.println("回退出栈1次");
        articleMemento = articleMementoManager.getMemento();
        article.undoFromMemento(articleMemento);
        System.out.println("回退1次:" + article);

        System.out.println("回退出栈2次");
        articleMemento = articleMementoManager.getMemento();
        article.undoFromMemento(articleMemento);
        System.out.println("暂存回退 end");
        System.out.println("回退2次:" + article);
    }

}
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

执行结果:

原始:Article{title='Java设计模式A', content='内容A', image='图片A'}
修改笔记 start
修改笔记 end
修改1次后:Article{title='Java设计模式B', content='内容B', image='图片B'}
修改2次后:Article{title='Java设计模式C', content='内容C', image='图片C'}
暂存回退 start
回退出栈1次
回退1次:Article{title='Java设计模式B', content='内容B', image='图片B'}
回退出栈2次
暂存回退 end
回退2次:Article{title='Java设计模式A', content='内容A', image='图片A'}
1
2
3
4
5
6
7
8
9
10
11

# 三、源码中的应用

# spring 的 StateManageableMessageContext

StateManageableMessageContext 接口继承自 MessageContext,这个接口有3个方法:

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
	 */
	public 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
	 */
	public 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)
	 */
	public void setMessageSource(MessageSource messageSource);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

这就是使用了备忘录模式。


上次更新: 2020-08-21 09:02:51(10 小时前)