设计模式---备忘录(Memento)模式

1 引言

在我们写文档写代码的时候,总想回到以前的某个状态,怎么实现了?按ctrl+z或者command+z实现,助我们恢复到想要的某个状态。在软件设计中,有一种设计模式与之对应---备忘录(Memento)模式。

2 定义

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。

3 结构与实现

备忘录模式主要包含以下三个角色:

1.发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。

2.备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。

3.管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

结构如下图所示(来自引用2):

4 优缺点 

备忘录模式是一种对象行为型模式,其主要优点如下:

1.提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。

2.实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。

3.简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

其主要缺点是:

1.资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

5 应用场景

1.需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。

2.需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。

6 代码示例

现在有四大美女任你挑选,你可以左右滑动查看美女的具体信息,当你看完最后一个美女,想要选择前面的美女时,通过向管理者输入编号,就可以找到对应的美女嘉宾。

6.1 备忘录美女 BeautifulGirl

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-14 10:44
 **/
@Data
@AllArgsConstructor
public class BeautifulGirl {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private int age;

    /**
     * 擅长的才艺
     */
    private String art;
}

6.2 发起人 Originator

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-14 10:49
 **/
@Data
public class Originator{

    private BeautifulGirl girl;

    public Originator(BeautifulGirl girl){
        this.girl = girl;
    }

    //存储
    public BeautifulGirl createMemento() {
        return this.getGirl();
    }

    //恢复
    public void restoreMemento(BeautifulGirl girl){
        this.setGirl(girl);
    }
}

6.3 管理者 Caretaker

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-14 11:21
 **/
public class Caretaker {
    private final Map<Integer, BeautifulGirl> originator = new HashMap<>(16);

    public void setMemento(int seq, BeautifulGirl girl){
        this.originator.put(seq, girl);
    }

    public BeautifulGirl getMemento(int id){
        return this.originator.get(id);
    }
}

6.4 主函数

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-14 10:38
 **/
public class MainClass {
    public static void main(String[] args) throws CloneNotSupportedException {
        BeautifulGirl[] girls = new BeautifulGirl[]{
                new BeautifulGirl("貂蝉", 22, "跳舞"),
                new BeautifulGirl("西施", 18, "画画"),
                new BeautifulGirl("王昭君", 20, "弹琵琶"),
                new BeautifulGirl("杨玉环", 19, "唱歌")
        };

        //从第一个开始选择
        Originator originator = new Originator(girls[0]);
        Caretaker caretaker = new Caretaker();
        //存储选择的第一个
        caretaker.setMemento(1, originator.createMemento());
        //选择第二个
        originator.setGirl(girls[1]);
        //存储第二个
        caretaker.setMemento(2, originator.createMemento());
        //选择第三个
        originator.setGirl(girls[2]);
        //存储第三个
        caretaker.setMemento(3, originator.createMemento());
        //选择第四个
        originator.setGirl(girls[3]);
        //存储第四个
        caretaker.setMemento(4, originator.createMemento());

        //最后到底选择第几个了?
        originator.restoreMemento(caretaker.getMemento(3));

        System.out.println(originator.getGirl());
    }
}

6.5 运行结果

1.debug到最后一行时变量的状态

2.运行完成的状态

7 总结

本文简单的介绍了备忘录设计模式,通俗理解就是把曾经的状态存储起来,当我们想要“后悔”的时候,有迹可循。通过一个简单的类似于相亲的代码例子,把曾经见过的女孩都存储起来,当我们想要选择以前见过的女孩儿时,只需要找到相亲管理者,说出序号,就能找见对应的女孩。

在发起人代码中,我们可以结合原型模式,复制一份我们手中的女孩儿信息给管理者,这里就不放代码了。

8 引用

1.《大话设计模式》

2.备忘录模式(详解版)

9 源代码

design-pattern-learning/src/com/hz/design/pattern/memento at main · airhonor/design-pattern-learning · GitHub

猜你喜欢

转载自blog.csdn.net/honor_zhang/article/details/120758668
今日推荐