行为型:备忘录模式

目录

1、核心思想

2、实现方式

2.1 模式结构

2.2 实现案例

3、优缺点分析

4、适用场景


1、核心思想

目的:在不破坏元对象封装性的前提下捕获其在某些时刻的内部状态,并像历史快照一样将它们保留在元对象之外,以备恢复之用。

举例

1> 文本编辑器的撤销/重做功能

2> 数据库事务回滚

3> 浏览器前进后退功能

2、实现方式

2.1 模式结构

三种主要角色:

  • Originator(元/原发器)​:需要保存状态的对象,负责创建备忘录从备忘录恢复状态。比如编辑器中的文档对象
  • Memento(备忘录)​:与元对象相仿,存储元对象内部状态的快照,仅允许元访问其内部数据,通常设计为不可变对象,一个状态对应一个备忘录对象。
  • CareTaker(看护人/负责人)​:历史记录的维护者,持有所有记录的历史记录,并且提供对元数据对象的恢复操作,如撤销undo()、重做redo()等,一般不提供对历史记录的修改。

模式变体与优化:

  • 增量备忘录:仅保存状态变化部分而非全量数据,减少内存占用
  • 结合原型模式:通过克隆(Clone)快速生成备忘录,适用于复杂对象状态的保存

2.2 实现案例

文档撤销功能:

// 1、元:文档类
public class Doc {

    private String title;//文档标题
    private String body;//文档内容

    public Doc(String title) {
        this.title = title; //新建文档先命名
        this.body = "";//新建文档内容为空
    }

    //省略set、get

    public History createHistory() {
        return new History(body);//创建历史记录
    }

    public void restoreHistory(History history) {
        this.body = history.getBody();//恢复历史记录
    }
}

// 2、备忘录:历史快照类
public class History {
    private String body;//用于备忘文档内容

    public History(String body) {
        this.body = body;
    }

    public String getBody() {
        return body;
    }
}

// 3、看护人
public class Editor {
    private Doc doc;
    private Stack<History> historyRecords;//历史记录列表

    public Editor(Doc doc) {
        System.out.println("<<<打开文档" + doc.getTitle());
        this.doc = doc;//载入文档
        historyRecords = new Stack<>();//初始化历史记录列表
        backup();//载入文档后保存第一份历史记录
        show();//显示内容
    }

    public void append(String txt) {
        System.out.println("<<<插入操作");
        doc.setbody(doc.getBody() + txt);
        backup();//添加后保存一份历史记录
        show();
    }

    public void delete() {
        System.out.println("<<<删除操作");
        doc.setbody("");
        backup();//删除后保存一份历史记录
        show();
    }

    private void show() {
        System.out.println(doc.getBody());
        System.out.println("文档结束>>>\n");
    }

    //添加快照
    private void backup() {
        historyRecords.push(doc.createHistory());
    }

    //撤销操作
    public void undo() {
        System.out.println(">>>撤销操作");
        History history = historyRecords.pop();
        if(history != null) {
            doc.setBody(history);//取出历史记录并恢复至文档
            show();
        }
    }

}


// 4、客户端
public class Client {
    public static void main(String[] args) {
        Editor editor = new Editor(new Doc("《AI的觉醒》"));
        editor.append("第一章 混沌初开");
        editor.append("\n  正文部分");
        editor.append("\n第二章 荒漠之花");
        editor.delete();
        editor.undo();
    }
}


3、优缺点分析

优点:

  • 封装性:不暴露对象内部状态,符合迪米特法则。

  • 简化原发器:将状态管理职责分离到备忘录和负责人。

  • 灵活撤销/重做:支持多次撤销(通过栈或列表管理历史状态)。

  • 状态快照:可保存任意时刻的状态,用于审计或调试。

缺点:

  • 内存消耗:频繁保存大对象状态可能导致内存占用高。(为备忘录加上容量限制,如总保存最近的20条记录)

  • 性能开销:深拷贝复杂对象可能影响性能。

  • 维护成本:需确保备忘录与原发器状态同步。

4、适用场景

  • 撤销/重做功能

    • 如文本编辑器、绘图软件、游戏操作回退。

  • 事务回滚

    • 数据库操作失败时恢复到之前的状态。

  • 状态快照存档

    • 游戏存档、系统配置备份。

  • 协作编辑历史

    • 如Google Docs的版本历史功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熙客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值