首页 > 其他分享 >备忘录模式:如何在聊天会话中记录历史消息?

备忘录模式:如何在聊天会话中记录历史消息?

时间:2024-09-21 17:51:33浏览次数:12  
标签:String 备忘录 对象 title public 会话 聊天 id

相较于其他的设计模式,备忘录模式不算太常用,但好在这个模式理解、掌握起来并不难,代码实现也比较简单,应用场景就更是比较明确和有限,一般应用于编辑器或会话上下文中防丢失、撤销、恢复等场景中。下面就一起来了解一下吧。

一、模式原理分析

备忘录模式的原始定义是:捕获并外部化对象的内部状态,以便以后可以恢复,所有这些都不会违反封装。

这个定义是非常简单的,我们可以直接来看看备忘录模式对应的 UML 图:

从该 UML 图中,我们能看出备忘录模式包含两个关键角色。

  • 原始对象(Originator):除了创建自身所需要的属性和业务逻辑外,还通过提供方法 create() 和 restore(memento) 来保存和恢复对象副本。

  • 备忘录(Memento):用于保存原始对象的所有属性状态,以便在未来进行撤销操作。

下面我们再来看看 UML 对应的代码实现。首先,我们创建原始对象 Originator,对象中有四个属性,分别是 state 用于显示当前对象状态,id、name、phone 用来模拟业务属性,并添加 get、set 方法、create() 方法用于创建备份对象,restore(memento) 用于恢复对象状态。

public class Originator {
    private String state = "原始对象";  //打印当前状态
    private String id;
    private String name;
    private String phone;
    public Originator() {
    }
    //省略get、set方法

    public Memento create() {
        return new Memento(id, name, phone);
    }
    public void restore(Memento m) {
        this.state = m.getState();
        this.id = m.getId();
        this.name = m.getName();
        this.phone = m.getPhone();
    }
    @Override
    public String toString() {
        return "Originator{" +
                "state='" + state + '\'' +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}

然后,再来创建备忘录对象 Memento,你会发现备忘录对象几乎就和原始对象的属性一模一样。

public class Memento {
    private String state = "从备份对象恢复为原始对象";  //打印当前状态
    private String id;
    private String name;
    private String phone;
    public Memento(String id, String name, String phone) {
        this.id = id;
        this.name = name;
        this.phone = phone;
    }
    //省略get、set方法

    @Override
    public String toString() {
        return "Memento{" +
                "state='" + state + '\'' +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}

接着我们运行一个单元测试,如下代码:

public class Demo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        originator.setId("1");
        originator.setName("mickjoust");
        originator.setPhone("1234567890");
        System.out.println(originator);
        Memento memento = originator.create();
        originator.setName("修改");
        System.out.println(originator);
        originator.restore(memento);
        System.out.println(originator);
    }
}
//输出结果
Originator{state='原始对象', id='1', name='mickjoust', phone='1234567890'}
Originator{state='原始对象', id='1', name='修改', phone='1234567890'}
Originator{state='从备份对象恢复为原始对象', id='1', name='mickjoust', phone='1234567890'}

从上面的代码实现和最后输出的结果可以看出,备忘录模式的代码实现其实是非常简单的,关键点就在于要能保证原始对象在某一个时刻的对象状态被完整记录下来

二、使用场景分析

一般来讲,备忘录模式常用的使用场景有这样几种。

  • 需要保存一个对象在某一个时刻的状态时。比如,在线编辑器中编写文字时断网,需要恢复为断网前的状态。

  • 不希望外界直接访问对象的内部状态时。比如,在包裹配送的过程中,如果从仓库运送到配送站,只需要显示“在运行中”,而具体使用汽车还是飞机,这个用户并不需要知道。

为了更好地理解备忘录模式的适用场景,接下来我们还是通过一个简单的例子来为你演示一下。

假设现在正在管理一个博客系统,你经常需要创建 Blog 对象,但是有一些作者在写 Blog 的过程中可能会出现断网的情况,这时就需要你保存 Blog 对象在这个时刻的状态信息,后续等作者重新联网后,能够及时地恢复其断网前的状态。那具体该怎么来做呢?

可以先创建一个 Blog 对象,该对象中包含 id、title 和 content,分别代表了 Blog 的唯一编号、标题和内容;并提供创建备忘录的 createMemento() 和 restore(BlogMemento m) 方法,分别用于创建备忘录和通过备忘录来恢复原始的 Blog 对象。

public class Blog {
    private long id;
    private String title;
    private String content;
    public Blog(long id, String title) {
        super();
        this.id = id;
        this.title = title;
    }
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    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 BlogMemento createMemento() {
        BlogMemento m = new BlogMemento(id, title, content);
        return m;
    }
    public void restore(BlogMemento m) {
        this.id = m.getId();
        this.title = m.getTitle();
        this.content = m.getContent();
    }
    @Override
    public String toString() {
        return "Blog{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

然后,再来创建一个 Blog 的备忘录对象 BlogMemento,同样是复制 Blog 所需要的所有属性内容。

public class BlogMemento {
    private final long id;
    private final String title;
    private final String content;
    public BlogMemento(long id, String title, String content) {
        super();
        this.id = id;
        this.title = title;
        this.content = content;
    }
    public long getId() {
        return id;
    }
    public String getTitle() {
        return title;
    }
    public String getContent() {
        return content;
    }
}

这样基于 Blog 对象的备忘录就创建好了。最后,我们依然还是运行一段单元测试代码来看看运行结果。

public class Client {
    public static void main(String[] args) {
        Blog blog = new Blog(1, "My Blog");
        blog.setContent("ABC");      //原始的文章内容
        System.out.println(blog);
        BlogMemento memento = blog.createMemento();   //创建blog的备忘录
        blog.setContent("123");      //改变内容
        System.out.println(blog);
        blog.restore(memento);       //撤销操作
        System.out.println(blog);    //这时会显示原始的内容
    }
}

从这个运行结果中,你会发现使用备忘录模式能非常方便地进行撤销操作。当你在编辑文章内容时,其实就是在修改 content 内容,这时备忘录会记录特定时间点里的对象状态,如果这时需要撤销修改,那么就会恢复到原来的对象状态。

所以说,备忘录模式在频繁需要撤销与恢复的场景中能够发挥很好的作用

三、为什么使用备忘录模式?

分析完备忘录模式的原理和使用场景后,我们再来说说使用备忘录模式的原因,可总结为以下两个。

第一个,为了记录多个时间点的备份数据。 与传统备份不同的是,备忘录模式更多是用来记录多个时间点的对象状态数据,比如编辑器、聊天会话中会涉及多次操作和多次交互对话,一方面是为了记录某个时间点数据以便以后运营用来做数据分析,另一方面是为了能够通过多次数据快照,防止客户端篡改数据。

第二个,需要快速撤销当前操作并恢复到某对象状态。 比如,微信中的撤回功能其实就是备忘录模式的一种体现,用户发错信息后,需要立即恢复到未发送状态。

四、备忘录模式的优缺点是什么?

通过上述分析,我们也可以得出备忘录模式主要有以下优点。

  • 能够快速撤消对对象状态的更改。 比如,在编辑器中不小心覆盖了一段重要的文字,使用 undo 操作能够快速恢复这段文字。

  • 能够帮助缓存记录历史对象状态。比如,在客服会话聊天中,对于某一些重要的对话(退换货、价保等),我们会记录这些对象数据,传统的做法是调用一次服务接口,一旦服务出现故障就很容易导致聊天回复速度变慢;而使用备忘录模式则能够记录这些重要的数据信息(用户提供的订单数据),而不需要反复查询接口,这样能提升回复客户的效率。

  • 能够提升代码的扩展性。 备忘录模式是通过增加外部对象来保存原始对象的状态,而不是在原始对象中新增状态记录,当不再需要保存对象状态时就能很方便地取消这个对象。同理,新增备忘录对象也非常容易。

同样,备忘录模式也有一些缺点。

  • 备忘录会破坏封装性。 因为当备忘录在进行恢复的过程中遇见错误时,可能会恢复错误的状态。比如,备份的对象状态中有需要调用数据库等外部服务时,在恢复过程中如果遇见数据库宕机,那么可能恢复的对象数据就会存在错误。

  • 备忘录的对象数据很大时,读取数据可能出现内存用尽的情况。 比如,在编辑器中加入高清的图片,如果直接记录图片本身可能会导致内存被用尽,进而导致系统出现崩溃的情况。

备忘录模式也叫快照模式,具体来说,就是通过捕获对象在某一个时刻的对象状态,再将其保存到外部对象,以便在需要的时候恢复对象到指定时刻下的状态。

备忘录模式的应用场景比较局限,主要是用来备份、撤销、恢复等,这与平时我们常说的“备份”看上去很相似,但实际上两者的差异是很大的:备忘录模式更侧重于代码的设计和实现,支持简单场景中的应用,比如记录 Web 请求中的 header 信息等;而备份更多是以解决方案的形式出现,比如异地容灾备份、数据库主从备份等所支持的是更复杂的业务场景,备份的数据量往往也更大。

因此,在使用备忘录模式时,一定不要误认为它就是万能的备份模式,要合理评估对象所使用的内存空间,再确定是否使用备忘录模式。

文章(专栏)将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发

标签:String,备忘录,对象,title,public,会话,聊天,id
From: https://blog.51cto.com/jiangyi/12075022

相关文章

  • Golang在线客服系统源码:基于Gin框架,Websocket即时通讯企业网站客服聊天源码,包括后台管
    唯一客服系统是一款基于Golang的Gin框架构建的在线客服解决方案,支持独立部署,确保数据的私密性和安全性。它具备自适应的响应式设计,能够完美适配PC端、移动端以及APP内嵌等多种场景。客服端提供PC后台管理功能,实现实时消息接收和交流。此外,为了满足移动端回复需求,系统还利用uniapp......
  • 天润融通创新功能,将无效会话转化为企业新商机
    “您好,请问有什么可以帮您?”“......”一个新的咨询会话进来,但客户却并不说话,这种情况客服人员肯定不会陌生,它一般被称为“无效会话”。如今“无效会话”越来越多,已经成为困扰无数企业的难题。毕竟客户没有提出任何问题,客服也就无从服务。这个时候,座席人员如果一直等待就会占用精力......
  • 请问怎么恢复微信聊天记录?我来啦
    移动互联网的时代,微信作为一个聊天工具,自带很多小程序,用起来非常的方便,微信用户也因此越来越多。但是用过微信的人都知道,微信其实有一个很大的漏洞,就是对话框删除了聊天记录就没了,今天小编拒贷大家恢复微信聊天记录。方法一微信自带恢复技巧如果你的微信是在PC端进行登录的,在......
  • 基于Uni-app前端框架的SUMER UI3.0组件库!一端开发,多端运行!本组件库可快速二次开发各种
    基于Uni-app前端框架的SUMERUI3.0组件库!一端开发,多端运行!本组件库可快速二次开发各种类别各行业模板,包括:商城、视频、直播、聊天、支付、新闻、社区、地图、导航、出行、社区、博客等sumer-ui介绍基于uView微信小程序UI组件库,兼容vue3。本插件是SUMER组件库,只提供组件......
  • uniapp精仿支付宝UI界面,首页/理财/消息/生活/口碑/我的,还有模拟支付宝扫码支付/收付款
    uniapp精仿支付宝UI界面,首页/理财/消息/生活/口碑/我的,还有模拟支付宝扫码支付/收付款等功能,界面漂亮颜值高,视频商城小工具等,蚂蚁森林种树养鸡农场偷菜样样齐用于视频,商城,直播,聊天等sumer-alipay介绍uniapp精仿支付宝UI界面,首页/理财/消息/生活/口碑/我的,还有模拟支付宝......
  • uniapp精仿微信源码,基于SumerUI和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,视
    uniapp精仿微信源码,基于SumerUI和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,视频商城小工具等,朋友圈视频号即时聊天用于视频,商城,直播,聊天,等等场景,源码分享sumer-weixin介绍uniapp精仿微信,基于SumerUI3.0和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,视频......
  • Spring Cloud 7.1: 会话保持
    会话保持是微服务绕不开的一个话题。在springcloud中采用redis保存session信息的方式来保持会话。接下来我们在前面工程的基础上配置一下redis,实现会话保持。首先看一下保持不了的会话是什么样。在service1和service2中分别新建会话模块,创建ConversationControllerservice1 Conve......
  • LLMChat入门指南 - 基于Flutter和FastAPI的大语言模型聊天应用
    LLMChat-您的AI聊天助手......
  • Unity使用TextMeshPro实现聊天图文混排
    本文来自:https://developer.aliyun.com/article/10666231.文字自适应问题。2.图文混排问题。UI界面1.创建滑动列表首先创建一个可以上下滑动的列表,命名为chat_scroll2.创建聊天预制因为聊天是两人以上的,自己的聊天显示在右侧,别人的聊天消息显示在左侧。因此需要制作两个聊天......
  • 如何查看电脑端的微信聊天记录?今天告诉你!五步掌握微信聊天记录查看与管理技巧!【企业必
    你是否曾经遇到过这样的场景:在忙碌的工作日中,需要快速查找某个重要客户的微信聊天记录,却发现电脑上的微信界面早已被无数条消息淹没?或者作为企业管理者,你希望能够有效监控员工的微信沟通,确保工作的高效与合规性?今天,我们就来详细解答这个问题,教你五步轻松掌握电脑端微信聊天......