【设计模式系列21】备忘录模式:我简单到已经让人彻底忽略了

备忘录模式原理及示例分析

  • 设计模式系列总览
  • 前言
  • 什么是备忘录模式
  • 备忘录模式示例
  • 备忘录模式角色
  • 备忘录模式应用场景
  • 备忘录模式优缺点
  • 总结

设计模式系列总览

设计模式 飞机票
三大工厂模式 登机入口
策略模式 登机入口
委派模式 登机入口
模板方法模式 登机入口
观察者模式 登机入口
单例模式 登机入口
原型模式 登机入口
代理模式 登机入口
装饰者模式 登机入口
适配器模式 登机入口
建造者模式 登机入口
责任链模式 登机入口
享元模式 登机入口
组合模式 登机入口
门面模式 登机入口
桥接模式 登机入口
中介者模式 登机入口
迭代器模式 登机入口
状态模式 登机入口
解释器模式 登机入口
备忘录模式 登机入口
命令模式 登机入口
访问者模式 登机入口
软件设计7大原则和设计模式总结 登机入口

前言

备忘录模式是一个非常简单的设计模式,简单到已经让我们忽略了这种设计模式的存在了。备忘录模式这个名字可能还是有人会觉得稍微有点陌生,但是它的另一个名字快照模式听起来可能心里就会有点明白这到底是一种什么设计模式了。接下来就让我们看看备忘录模式吧

什么是备忘录模式

备忘录模式(Memento Pattern)又称之为快照模式(Snapshop Pattern)或者令牌模式(Token Pattern),是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样我们就可以在需要的时候将该对象恢复到原先保存的状态了,备忘录模式属于行为型模式。

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

好了,装逼时刻又到了:Talk is cheap,Show you the code,先看一个非常简单的例子。

备忘录模式示例

下面我们就以常见的富文本编辑器来编辑文章的功能为例来写一个简单的示例来看看备忘录模式是如何实现的。
1、首先建立一个类来保存最新文章信息:

package com.zwx.design.pattern.memento;

import java.util.Date;

public class ArticleText {
     
    private String title;
    private String content;
    private Date createTime;

    public ArticleText(String title, String content, Date createTime) {
     
        this.title = title;
        this.content = content;
        this.createTime = createTime;
    }

    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 Date getCreateTime() {
     
        return createTime;
    }

    public void setCreateTime(Date createTime) {
     
        this.createTime = createTime;
    }

    public ArticleMemento saveToMemento(){
     
        ArticleMemento articleMemento = new ArticleMemento(this.title,this.content,this.createTime);
        return articleMemento;
    }

    public void getArticleFromMemento(ArticleMemento articleMemento){
     
        this.title = articleMemento.getTitle();
        this.content = articleMemento.getContent();
        this.createTime = articleMemento.getCreateTime();
    }
}

注意:这里面除了getter/setter方法之外还有一个方法用来备份,一个方法用来还原。

2、建立一个类用来保存历史数据,这个类的信息必须要和原始类一样,否则无法完全备份:

package com.zwx.design.pattern.memento;

import java.util.Date;

public class ArticleMemento {
     
    private String title;
    private String content;
    private Date createTime;

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

    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 Date getCreateTime() {
     
        return createTime;
    }

    public void setCreateTime(Date createTime) {
     
        this.createTime = createTime;
    }
}

3、然后还需要一个类来管理历史快照信息:

package com.zwx.design.pattern.memento;

import java.util.ArrayList;
import java.util.List;

public class ArticleCaretaker {
     
    private final List<ArticleMemento> list = new ArrayList<>();

    public ArticleMemento getArticle(int index){
     
        return list.get(index);
    }

    public void setArticle(ArticleMemento articleMemento){
     
        list.add(articleMemento);
    }
}

4、最后来一个测试类测试一下:

package com.zwx.design.pattern.memento;

import java.util.Date;

public class TestMemento {
     
    public static void main(String[] args) {
     
        ArticleCaretaker articleCaretaker = new ArticleCaretaker();

        ArticleText articleText = new ArticleText("标题1","内容1",new Date());
        ArticleMemento articleMemento = articleText.saveToMemento();
        articleCaretaker.setArticle(articleMemento);//备忘1次

        articleText = new ArticleText("标题2","内容2",new Date());
        System.out.println(String.format("修改后的标题为【%s】,内容为【%s】",articleText.getTitle(),articleText.getContent()));

        articleText.getArticleFromMemento(articleCaretaker.getArticle(0));
        System.out.println(String.format("还原后的标题为【%s】,内容为【%s】",articleText.getTitle(),articleText.getContent()));
    }
}

输出结果如下:

修改后的标题为【标题2】,内容为【内容2】
还原后的标题为【标题1】,内容为【内容1

这就是一个备忘录模式的示例,这个设计模式应该来说还是非常简单的。

备忘录模式角色

从上面示例中,我们可以得出迭代器模式主要有3个角色:

  • 发起人角色(Originator):负责创建一个备忘录,记录自身需要保存的状态,而且需要具备状态的回滚功能。
  • 备忘录角色(Memento):用于存储Originator角色的内部状态,且可以防止Originator以外的对象进行访问。
  • 备忘录管理员角色(Caretaker):负责存储,管理备忘录功能。且其本身应该无法对备忘录的内容进行访问。

备忘录模式应用场景

备忘录模式作为一个程序员应该没有没使用过的,像比如svn,git等都是提供了历史版本的管理功能,这些就是备忘录模式的体现,像还有富文本的编辑之类的都可以使用备忘录模式来进行实现,还有服务器的快照功能也可以是我们回退到历史状态。备忘录模式一般用于以下场景:

  • 1、需要保存历史快照的场景
  • 2、希望在对象之外保存状态,且除了自己其他对象无法访问状态的具体保存内容

备忘录模式优缺点

优点:

  • 1、简化了发起人的的职责,将状态的存储和获取进行了隔离,而且客户端无需关心状态的保存细节。
    缺点:
  • 1、消耗资源,如果每个快照的内容都非常大,会消耗大量内存。

总结

备忘录模式是一个简单的非常容易让人彻底忽略的设计模式。本文主要介绍了备忘录模式的基本使用,并通过一个简单的示例来帮助更好的理解备忘录模式。

请关注我,和孤狼一起学习进步

你可能感兴趣的:(设计模式,java,设计模式,备忘录,Memento)