大聪明教你学Java设计模式 | 第十七篇:备忘录模式

251 阅读5分钟

前言

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情

🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。

🍊支持作者: 点赞👍、关注💖、留言💌~

大聪明在写代码的过程中发现设计模式的影子是无处不在,设计模式也是软件开发人员在软件开发过程中面临的一般问题的解决方案。大聪明本着“独乐乐不如众乐乐”的宗旨与大家分享一下设计模式的学习心得。

备忘录模式

🍓🍓什么是备忘录模式🍓🍓

在讲备忘录模式之前,我们先来看一下它的定义👇

备忘录模式(Memento Pattern)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。备忘录模式又叫快照模式

看了备忘录模式的定义,我们是不是感觉有些熟悉?没错,它就像是“后悔药”一样,当我们犯错的时候,就可以通过“后悔药”来帮助我们“倒转时空”,从而可以让我们修复之前所犯下的错误,这就是备忘录模式的意义。而且在很多应用软件中都给我们提供了“后悔药”,比如 Word、TXT文件、Eclipse、IDEA 等等软件在编辑时按 Ctrl+Z 组合键都可以撤销当前操作,使文档恢复到之前的状态;除此之外,还有在浏览器中的后退键、数据库事务管理中的回滚操作、玩游戏时的中间结果存档功能、数据库与操作系统的备份操作、棋类游戏中的悔棋功能等等都是备忘录模式的体现。

我们看了备忘录模式的定义和其具体的示例,我们来一起分析一下备忘录模式中包含了哪写角色~

既然我们需要撤销当前操作,那么就需要一个角色来发起撤销请求,同时要去备忘录中找到之前所保存的信息,那么这第一个角色就是发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息; 在定义中提到了需要捕获内部状态并对其进行保存,这就引出了第二个角色,那就是备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人; 有了备忘录角色后,我们还需要对备忘录进行管理,这也就是第三个角色,管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

🍓🍓备忘录模式的实现🍓🍓

在上面我们分析出了备忘录模式中所包含三种角色,那么接下来我们就实现一个简单的备忘录模式👇

Memento 包含了要被恢复的对象的状态;Originator 创建并在 Memento 对象中存储状态;Caretaker 对象负责从 Memento 中恢复对象的状态。

🍎🍎创建备忘录(Memento)类🍎🍎

/**
 * 备忘录类
 * @description: Memento
 * @author: 庄霸.liziye
 * @create: 2022-04-18 21:44
 **/
public class Memento {

    /**
     * 状态
     */
    private String state;

    public Memento(String state){
        this.state = state;
    }

    public String getState(){
        return state;
    }
}

🍎🍎创建发起人(Originator)类🍎🍎

/**
 * 发起人
 * @description: Originator
 * @author: 庄霸.liziye
 * @create: 2022-04-18 21:47
 **/
public class Originator {
    private String state;

    public void setState(String state){
        this.state = state;
    }

    public String getState(){
        return state;
    }

    /**
     * 保存状态到备忘录
     * @return
     */
    public Memento saveStateToMemento(){
        return new Memento(state);
    }

    /**
     * 从备忘录中获取状态
     * @param Memento
     */
    public void getStateFromMemento(Memento Memento){
        state = Memento.getState();
    }
}

🍎🍎创建管理者(CareTaker)类🍎🍎

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

/**
 * 管理者
 * @description: CareTaker
 * @author: 庄霸.liziye
 * @create: 2022-04-18 21:53
 **/
public class CareTaker {
    
    private List<Memento> mementoList = new ArrayList<Memento>();

    public void add(Memento state){
        mementoList.add(state);
    }

    public Memento get(int index){
        return mementoList.get(index);
    }
}

🍎🍎模拟撤销操作🍎🍎

/**
 * @description: Test
 * @author: 庄霸.liziye
 * @create: 2022-04-11 11:31
 **/
public class Test {

    public static void main(String[] args) {
        Originator originator = new Originator();
        CareTaker careTaker = new CareTaker();
        originator.setState("状态 #1");
        originator.setState("状态 #2");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("状态 #3");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("状态 #4");

        System.out.println("当前状态: " + originator.getState());
        System.out.println("-----开始执行撤销操作-----");
        originator.getStateFromMemento(careTaker.get(0));
        System.out.println("第一次保存时的状态:" + originator.getState());
        originator.getStateFromMemento(careTaker.get(1));
        System.out.println("第二次保存的状态:" + originator.getState());
    }
}

🍎🍎运行结果🍎🍎 在这里插入图片描述

🍓🍓备忘录模式的优、缺点🍓🍓

最后我们总结一下备忘录模式的优点与缺点👇

🍌🍌优点🍌🍌

🍋 它给我们提供了一种可以恢复状态的机制,可以帮助我们比较方便地回到某个历史的状态;同时实现了信息的封装,使得我们不需要关心状态的保存细节。

🍌🍌缺点🍌🍌

🥝 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

P.S. 相信各位小伙伴都知道 Word、TXT文件等等,关闭后再重新打开就无法再进行撤销操作了,个人猜测这是一种节约内存的处理手段,当文件关闭后就清空备忘录中存储的版本,从而达到节约资源的目的。

小结

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西