设计模式之 备忘录模式

备忘录模式是一种行为型设计模式,它允许你在不暴露对象实现细节的情况下,捕获和保存对象的内部状态。之后,可以通过保存的状态将对象恢复到原先的状态。备忘录模式的核心思想是"在不暴露对象的内部实现的情况下,保存对象的状态,并可以随时恢复这个状态"。

简单来说,备忘录模式帮助我们在某一时刻保存对象的状态,以便以后恢复。

一、备忘录模式的结构

备忘录模式由三个角色组成:

  1. Originator(发起人):负责创建备忘录和使用备忘录来恢复其内部状态。
  2. Memento(备忘录):备忘录对象包含了 Originator 的内部状态,可以在需要时提供给 Caretaker 使用。备忘录不应该对外暴露其内容。
  3. Caretaker(管理者):负责保存备忘录的对象,它不关心备忘录的内容,只知道如何保存和恢复备忘录。Caretaker 通常会持有多个备忘录,以便进行不同的状态恢复。

二、工作原理

备忘录模式的工作原理主要包括以下几个步骤:

  1. 保存状态:当对象的状态发生变化时,发起人对象(Originator)会创建一个备忘录对象(Memento),并将其当前状态存储在备忘录中。
  2. 恢复状态:当需要恢复对象的状态时,发起人会从管理者对象(Caretaker)处获取对应的备忘录,并使用备忘录中的状态信息恢复自身的状态。
  3. 管理备忘录:管理者对象(Caretaker)负责保存多个备忘录,并确保每个备忘录对应的对象状态是可以恢复的。

三、备忘录模式的实现示例

白箱备忘录

白箱备忘录模式是指备忘录对象暴露了内部状态的实现细节,管理者类(Caretaker)不仅能够保存和恢复备忘录,还可以直接访问备忘录中的数据。因此,备忘录是白箱的,它对外部类是透明的,管理者类可以直接读取和修改备忘录的内容。

发起人类
java 复制代码
public class Role {
    private int vit = 100;//生命
    private int atk = 100;//攻击
    private int def = 100;//防御

    public void fight(){
        this.vit = 0;
    }

    public Memento saveMemento(){
        return new Memento(vit,atk,def);
    }

    public void recoverMemento(Memento memento){
        this.vit = memento.getVit();
        this.atk = memento.getAtk();
        this.def = memento.getDef();
    }

    public void display(){
        System.out.println("生命力"+vit);
        System.out.println("攻击力"+atk);
        System.out.println("防御力"+def);
    }

}
备忘录类
java 复制代码
public class Memento {
    private int vit;
    private int atk;
    private int def;

    public int getVit() {
        return vit;
    }

    public int getAtk() {
        return atk;
    }

    public int getDef() {
        return def;
    }

    public Memento() {
    }

    public Memento(int vit, int atk, int def) {
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }
}
管理者类
java 复制代码
public class RoleStateCaretaker {
    private Memento memento;

    public void setRoleState(Memento memento){
        this.memento = memento;
    }

    public Memento getRoleState(){
        return memento;
    }
}
使用备忘录模式
java 复制代码
public class Client {
    public static void main(String[] args) {
        System.out.println("----------大战之前的状态--------");
        Role role = new Role();
        role.display();

        RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
        roleStateCaretaker.setRoleState(role.saveMemento());

        System.out.println("----------大战之后的状态--------");
        role.fight();
        role.display();


        System.out.println("----------恢复之前状态--------");
        role.recoverMemento(roleStateCaretaker.getRoleState());
        role.display();
    }
}
运行结果
黑箱备忘录

黑箱备忘录模式是指备忘录对象完全封装了发起人的状态,外部类 (包括管理者类 Caretaker)不能直接访问备忘录中的状态数据。换句话说,备忘录是黑箱的,发起人类是唯一能够读取和修改备忘录内部状态的类。管理者类(Caretaker)只负责保存和恢复备忘录对象,但无法查看备忘录中的数据内容。

针对上述示例,我们定义Memento接口供外部使用,Memento实现类为发起人类的私有内部类

发起人类
java 复制代码
public class Role {
    private int vit = 100;//生命
    private int atk = 100;//攻击
    private int def = 100;//防御



    public void fight(){
        this.vit = 0;
    }

    public Memento saveMemento(){

        return new RoleStateMemento(vit,atk,def);
    }

    public void recoverMemento(Memento memento){
        RoleStateMemento roleStateMemento = (RoleStateMemento) memento;
        this.vit = roleStateMemento.getVit();
        this.atk = roleStateMemento.getAtk();
        this.def = roleStateMemento.getDef();
    }

    public void display(){
        System.out.println("生命力"+vit);
        System.out.println("攻击力"+atk);
        System.out.println("防御力"+def);
    }

    private class RoleStateMemento implements Memento {
        private int vit;
        private int atk;
        private int def;

        public int getVit() {
            return vit;
        }

        public int getAtk() {
            return atk;
        }

        public int getDef() {
            return def;
        }


        public RoleStateMemento(int vit, int atk, int def) {
            this.vit = vit;
            this.atk = atk;
            this.def = def;
        }
    }

}
标记接口
java 复制代码
public interface Memento {
}
管理员类
java 复制代码
public class RoleStateCaretaker {
    private Memento memento;

    public void setRoleState(Memento memento){
        this.memento = memento;
    }

    public Memento getRoleState(){
        return memento;
    }
}
测试类
java 复制代码
public class Client {
    public static void main(String[] args) {
        System.out.println("----------大战之前的状态--------");
        Role role = new Role();
        role.display();

        RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
        roleStateCaretaker.setRoleState(role.saveMemento());

        System.out.println("----------大战之后的状态--------");
        role.fight();
        role.display();


        System.out.println("----------恢复之前状态--------");
        role.recoverMemento(roleStateCaretaker.getRoleState());
        role.display();
    }
}
运行结果

四、备忘录模式的优缺点

优点:
  1. 封装性好:备忘录模式可以在不暴露对象内部实现细节的情况下,保存和恢复对象的状态,从而保持了封装性。
  2. 灵活性高:可以随时创建和恢复对象的不同状态,支持"撤销"和"恢复"功能。
  3. 实现简单:备忘录模式可以通过简单的对象组合实现,逻辑清晰且易于理解。
缺点:
  1. 内存消耗:如果每次都创建备忘录来保存对象的状态,会导致大量备忘录对象的产生,可能会占用较多内存。
  2. 复杂性增加:当对象的状态非常复杂时,备忘录的管理可能会变得很复杂,尤其是涉及多个状态的保存与恢复时。
  3. 可能会泄露实现细节:尽管备忘录对象的设计要求不能暴露状态信息,但在某些情况下,备忘录对象的实现可能会不小心暴露对象的内部状态。
五、适用场景
  1. 撤销操作:当需要实现操作的撤销功能时,备忘录模式是一个理想的选择。它可以在执行操作前保存状态,以便在撤销时恢复到先前的状态。
  2. 状态恢复:当需要恢复某一时刻的对象状态时,备忘录模式提供了便捷的解决方案。
  3. 版本管理:在版本控制系统中,保存每个版本的状态(如文件的内容或数据库的状态),然后可以随时恢复到某个历史版本。
相关推荐
wirepuller_king4 小时前
创建Linux虚拟环境并远程连接,finalshell自定义壁纸
linux·运维·服务器
Yan-英杰4 小时前
【百日精通JAVA | SQL篇 | 第二篇】数据库操作
服务器·数据库·sql
风123456789~5 小时前
【Linux运维】查询指定日期的上月
linux·运维·服务器
CC.cc.6 小时前
Linux系统之systemctl管理服务及编译安装配置文件安装实现systemctl管理服务
linux·运维·服务器
爱写代码的小朋友8 小时前
华三交换机配置常用命令
运维·服务器·网络
wangjun51598 小时前
jenkins 参数化发布到服务器 publish over ssh、label、Parameterized publishing
服务器·ssh·jenkins
愚润求学8 小时前
【Linux】Linux权限
linux·服务器·语法
低头不见8 小时前
一个服务器算分布式吗,分布式需要几个服务器
运维·服务器·分布式
麻芝汤圆8 小时前
使用 MapReduce 进行高效数据清洗:从理论到实践
大数据·linux·服务器·网络·数据库·windows·mapreduce
赋创小助手9 小时前
Gartner预计2025年AI支出达6440亿美元:数据中心与服务器市场的关键驱动与挑战
运维·服务器·人工智能·科技·架构