03-JAVA设计模式-备忘录模式

备忘录模式

什么是备忘录模式

Java中的备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不破坏封装性的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后可以将对象恢复到原先保存的状态。

主要角色包括:

  • 发起者(Originator):需要保存和恢复状态的对象。它记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,并可以访问备忘录里的所有信息。
  • 备忘录(Memento):负责存储发起人的内部状态。它是一个临时中间对象,用于存储目标对象的初始相关属性信息。当需要恢复对象的状态时,备忘录提供这些内部状态给发起人。
  • 看护者(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能。但它不能对备忘录的内容进行访问与修改。

优点:

  • 状态保存与恢复:备忘录模式可以方便地保存和恢复对象的状态,使得对象的状态变化具有可追溯性。
  • 封装性:通过将对象的状态封装在备忘录对象中,备忘录模式可以保持对象的封装性,不会暴露内部状态给外部对象。
  • 简化撤销和重做操作:在需要实现撤销、重做等功能的场景中,备忘录模式可以大大简化操作,提高代码的清晰度和可维护性。

缺点:

  • 资源消耗:如果对象的状态较为复杂或状态变化频繁,备忘录模式可能会消耗较多的内存资源来保存状态。
  • 性能开销:频繁地创建和销毁备忘录对象可能会导致一定的性能开销。
  • 设计复杂性:如果对象的状态需要保密或访问权限受限,备忘录模式可能会增加设计的复杂性,并可能破坏对象的封装性。

常见应用场景:

  • 文本编辑器:在文本编辑器中,备忘录模式可以用于实现撤销和重做功能。当用户编辑文本时,编辑器可以定期保存文本状态到备忘录对象中。当用户需要撤销或重做操作时,编辑器可以恢复或重新应用这些状态。
  • 游戏存档:在电子游戏中,备忘录模式可以用于实现游戏的存档功能。当玩家选择保存游戏时,游戏可以将当前的游戏状态(如玩家位置、分数、物品等)保存到备忘录对象中。当玩家再次加载游戏时,游戏可以从备忘录对象中恢复状态,让玩家继续之前的游戏进度。
  • 数据库事务:在数据库操作中,备忘录模式可以用于实现事务的回滚功能。当执行一系列数据库操作时,可以将数据库的状态保存到备忘录对象中。如果事务执行失败或需要回滚,可以恢复到之前的状态。

案例

java实现控制台输入内容的回退

UML

实现步骤:

  • 创建发起者ScannerInput,定义保存输入内容字段input
  • 创建备忘录继承发起者,主要继承发起者的属性及get/set方法不再重复提供,提供创建备忘录及通过备忘录恢复状态的方法
  • 创建看护者,定义栈对备忘录进行管理,提供保存与获取备忘录的功能。但它不能对备忘录的内容进行访问与修改

实现代码

ScannerInput.java

java 复制代码
// 发起者
public class ScannerInput {
    // 输入内容
    protected String input;
    public ScannerInput(String input) {
        this.input = input;
    }
    public String getInput() {
        return input;
    }
    public void setInput(String input) {
        this.input = input;
    }
}

Originator.java

java 复制代码
// 备忘录
//  继承发起者,主要继承发起者的属性及get/set方法不再重复提供
//  提供创建备忘录及通过备忘录恢复状态的方法
public class Originator extends ScannerInput{

    public Originator(String input) {
        super(input);
    }

    // 创建备忘录
    public ScannerInput createMemento() {
        return new ScannerInput(this.input);
    }

    // 恢复
    public void restoreMemento(ScannerInput scannerInput) {
        this.input = scannerInput.getInput();
    }
}

Caretaker.java

java 复制代码
import java.util.Stack;

// 看护者
// * 对备忘录进行管理,提供保存与获取备忘录的功能。但它不能对备忘录的内容进行访问与修改。
public class Caretaker {
    // 定义栈管理备忘录
    private Stack<ScannerInput> stack = new Stack<ScannerInput>();

    // 压栈
    public void setScannerInput(ScannerInput scannerInput) {
        stack.push(scannerInput);
    }

    // 出栈
    public ScannerInput getScannerInput() {
        if(stack.size() == 0){
            System.out.println("已经不可以回退啦!");
        }
        return stack.pop();
    }
}

TestClient.java

java 复制代码
import java.util.Scanner;

public class TestClient {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一些文本,输入'exit'退出:");

        // 创建原发器对象并设置默认内容
        Originator originator = new Originator("");
        // 创建并保存备忘录
        Caretaker caretaker = new Caretaker();
        // 初始化压栈
        caretaker.setScannerInput(originator.createMemento());

        while (true) {
            String input = scanner.nextLine();
            if ("exit".equalsIgnoreCase(input)) {
                System.out.printf("你输入了:%s%n" , input);
                break;
            }
            // 回退操作
            else if ("back".equalsIgnoreCase(input)) {
                // 回退
                originator.restoreMemento(caretaker.getScannerInput());
                System.out.printf("回退上一步-你输入:%s%n 输入:back(回退上一步) exit(退出)%n" , originator.getInput());
            } else {
                // 设置内容
                originator.setInput(input);
                // 设置备忘录
                caretaker.setScannerInput(originator.createMemento());
                System.out.printf("你输入了:%s%n 输入:back(回退上一步) exit(退出)%n" , originator.getInput());
            }
        }

        scanner.close();
        System.out.println("已退出。");
    }
}

执行结果:

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

相关推荐
吾日三省吾码2 小时前
JVM 性能调优
java
弗拉唐3 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi773 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3434 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀4 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20204 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea
Ysjt | 深4 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
shuangrenlong4 小时前
slice介绍slice查看器
java·ubuntu
牧竹子4 小时前
对原jar包解压后修改原class文件后重新打包为jar
java·jar