浅谈设计模式 - 备忘录模式(十五)

简介: 浅谈设计模式 - 备忘录模式(十五)


浅谈设计模式 - 备忘录模式

前言

备忘录这个模式用的比较少,基本学完就可以忘记的一个模式,但是应用的情况还是不少,同时这个模式几乎“人手必备”,那就是典型的ctrl+z这个功能就可以看作备忘录的典型案例,我们的游戏存档也可以看作是一种备忘录的变形。

定义

备忘录模式重点在于记录住对象的状态,可以让对象的状态回到上一次操作的时候,同时可以保证不破坏封装性的前提下存在于其他的对象,这个模式需要注意的一个点是为了管理备忘的类,需要一个“辅助类”来进行备忘内容的统一管理,就好比我们的游戏的存档和读档一样。

应用场景

  1. 游戏的存档
  2. 恢复上一次状态
  3. 文字撤销
  4. 还原

优缺点:

  1. 不破坏对象的封装性保存对象的状态,可以让对象回到过去定义的任何一种状态。
  2. 用户不需要关系备忘的内容以及如何备忘,只需要关注备忘的数据即可。
  3. 备忘的数据过多会造成卡顿,并且有可能存在备忘记录丢失的可能性。

结构图:

备忘录模式主要分为三个点,第一:需要定义和备忘的内容有关的对外接口,并且将请求转发给具体的备忘器,然后备忘器备忘数据存储到具体的备忘实现对象来保存对象的状态,第二:定义备忘录存储接口传递对象的状态,记录当前的工作数据,第三需要使用具体的记录器恢复器对象来恢复具体的对象数据。

了解基本的设计对象之后下面来看下具体的实现结构图,这种模式有两种实现的结构方式,一种是嵌套类的结构,另一种是使用中间接口委托的形式进行处理,但是不管是嵌套结构还是中间接口委托的形式,基本都包含了下面的接口:

Memento(备忘录):包含了要被恢复的对象的状态,是快照的具体存储位置。

Originator(原发器):创建并在 Memento 对象中存储状态,可以看作是需要被快照的对象,通常包含某些状态数据。

Caretake(恢复器):负责从 Memento 中恢复对象的状态,可以看作是一个记录提取器或者说恢复器。

嵌套结构

嵌套结构的结构图如下所示,嵌套的结构下通常会把原发器嵌入到备忘录的接口里面,在部分的时候通过备忘录把数据进行恢复或者存储,恢复器负责对于原发器的状态进行还原的操作:

image.png

中间接口结构

中间接口结构针对一些不能使用嵌套类的情况,这时候我们只能委托给子类完成备份数据的处理,当然这样也有一种灵活性,就是备份的方式可以多样化。

image.png

案例代码

下面我们来看下上面的结构图的相关代码,由于这里使用的是java代码,所以我们直接使用嵌套类的形式完成:

Originator(原发器):创建并在 Memento 对象中存储状态,可以看作是需要被快照的对象,通常包含某些状态数据。

public class Originator {
    private String state;
    public Originator() {
    }
    public Originator(Memento memento) {
        memento = new Memento(state);
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
}

Memento(备忘录):包含了要被恢复的对象的状态,是快照的具体存储位置。

public class Memento {
    /**
     * 需要被备份的状态
     */
    private String state;
    public Memento(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
}

Caretake(恢复器):负责从 Memento 中恢复对象的状态,可以看作是一个记录提取器或者说恢复器。

public class CareTaker {
    private Memento memento;
    public CareTaker(Memento memento) {
        this.memento = memento;
    }
    public Memento getMemento() {
        return memento;
    }
    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

Client:最终的执行客户端,通过调用CareTaker进行将数据的状态进行还原:

public class Client {
    private Originator originator;
    public Client(Originator originator) {
        this.originator = originator;
    }
    /**
     * 恢复记录的状态
     */
    public void restore(CareTaker careTaker) {
        originator.setState(Optional.ofNullable(careTaker)
                .map(CareTaker::getMemento)
                .map(Memento::getState)
                .orElse("off"));
    }
}

最后是单元测试:

public class Main {
    public static void main(String[] args) {
        Originator originator = new Originator();
        originator.setState("on");
        System.out.println("备份状态"+ originator.getState());
        Memento memento = new Memento(originator.getState());
        CareTaker careTaker = new CareTaker(memento);
        //修改状态
        originator.setState("test");
        System.out.println("修改状态"+ originator.getState());
        Client client = new Client(originator);
        client.restore(careTaker);
        System.out.println("还原状态"+ originator.getState());
    }/*运行结果:
        备份状态on
        修改状态test
        还原状态on
    */
}

实际案例

不管是操作系统还是文本编辑,备忘和撤销的功能是必不可少的,所以我们用文本编辑器来讲述备忘录模式。最常见的情况是我们写好文章写到一半的时候关闭软件下次进入依然有原来的数据。这里我们使用“特殊方法”代替ctrl+s来进行数据的备份操作。

代码的内容和案例内容类似,只不过由于使用了对象需要注意对象的潜拷贝和深拷贝的问题。

首先我们建立文本对象:

public class Text {
    /**
     * 文本信息
     */
    private String info;
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}

下面是一个文本编辑器:

public class TextEditor {
    private Text text;
    public TextEditor(Text text) {
        this.text = text;
    }
    public void write(String info){
        text.setInfo(info);
    }
    public Text getText() {
        return text;
    }
    public void setText(Text text) {
        this.text = text;
    }
}

备忘录需要注意备份对象需要使用深拷贝

public class Memento {
    private Text text;
    public Text getText() {
        return text;
    }
    public void setText(Text text) {
        String info = text.getInfo();
        Text newText = new Text();
        newText.setInfo(info);
        this.text = newText;
    }
}

恢复器,最后要使用恢复器进行数据的恢复操作

public class CareTaker {
    private Memento memento;
    public CareTaker(Memento memento) {
        this.memento = memento;
    }
    /**
     * 恢复记录的状态
     */
    public void restore(TextEditor textEditor) {
        textEditor.getText().setInfo(memento.getText().getInfo());
    }
    public Memento getMemento() {
        return memento;
    }
    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

最后是测试代码:

public class Main {
    public static void main(String[] args) {
        Text text = new Text();
        TextEditor textEditor = new TextEditor(text);
        textEditor.write("d111111");
        Memento memento = new Memento();
        memento.setText(text);
        CareTaker careTaker = new CareTaker(memento);
        textEditor.write("66666");
        careTaker.restore(textEditor);
        System.out.println(careTaker.getMemento().getText().getInfo());
    }/*运行结果:
        浅拷贝:66666
        深拷贝:d111111
    */
}

总结

这个设计模式用的真的并不算很多,所以简单过一下即可。

写在最后

算是比较有意思的设计模式。

相关文章
|
6月前
|
设计模式 存储 Java
23种设计模式,备忘录模式的概念优缺点以及JAVA代码举例
【4月更文挑战第9天】备忘录模式是一种行为设计模式,它能在不破坏对象封装的前提下,捕获并保存对象的当前状态,以便后面可以恢复到这个状态。
86 0
|
6月前
|
设计模式 存储 Java
【设计模式】备忘录模式
【设计模式】备忘录模式
|
6月前
|
设计模式 存储 Java
Java设计模式【十九】:备忘录模式
Java设计模式【十九】:备忘录模式
40 0
|
2月前
|
存储 设计模式 安全
Java设计模式-备忘录模式(23)
Java设计模式-备忘录模式(23)
|
3月前
|
设计模式 算法
设计模式的基础问题之备忘录模式在软件开发的问题如何解决
设计模式的基础问题之备忘录模式在软件开发的问题如何解决
|
5月前
|
设计模式
备忘录模式-大话设计模式
备忘录模式-大话设计模式
|
4月前
|
设计模式 数据处理
iLogtail设计模式问题之什么是备忘录模式
iLogtail设计模式问题之什么是备忘录模式
|
5月前
|
设计模式 存储 Java
Java设计模式之备忘录模式详解
Java设计模式之备忘录模式详解
|
6月前
|
存储 设计模式 安全
探索设计模式的魅力:备忘录模式揭秘-实现时光回溯、一键还原、后悔药、历史的守护者和穿越时空隧道
备忘录模式是一种行为设计模式,允许在不破坏对象封装性的情况下保存和恢复对象的内部状态。该模式通过创建备忘录对象来存储发起人的状态信息,发起人可根据需要创建和恢复备忘录。管理者则负责保存和管理备忘录,但无法访问其内容。备忘录模式简化了状态管理,支持撤销操作和历史记录功能,提高了系统的灵活性和可用性。在实际应用中,备忘录模式常用于文本编辑器、游戏和数据库事务处理等场景,确保对象状态的安全恢复和有效管理。通过备忘录模式,开发人员可以更好地控制对象状态的变化,提升软件系统的健壮性和用户体验。
129 1
探索设计模式的魅力:备忘录模式揭秘-实现时光回溯、一键还原、后悔药、历史的守护者和穿越时空隧道
|
6月前
|
设计模式 存储 Go
[设计模式 Go实现] 行为型~备忘录模式
[设计模式 Go实现] 行为型~备忘录模式

热门文章

最新文章

  • 1
    C++一分钟之-设计模式:工厂模式与抽象工厂
    43
  • 2
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    49
  • 3
    C++一分钟之-C++中的设计模式:单例模式
    58
  • 4
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    38
  • 5
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    63
  • 6
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    58
  • 7
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    42
  • 8
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    50
  • 9
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    110
  • 10
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    78
  • 下一篇
    无影云桌面