设计模式之 备忘录模式

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

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

一、备忘录模式的结构

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

  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. 版本管理:在版本控制系统中,保存每个版本的状态(如文件的内容或数据库的状态),然后可以随时恢复到某个历史版本。
相关推荐
vvw&1 小时前
如何在 Ubuntu 22.04 上安装并开始使用 RabbitMQ
java·linux·运维·服务器·spring·ubuntu·rabbitmq
boy快快长大2 小时前
【NebulaGraph】查询案例(六)
java·服务器·数据库
hahaqi95272 小时前
uniapp生成h5后发布到服务器碰到的问题解决
运维·服务器·uni-app
isolusion3 小时前
Springboot配置嵌入式服务器
服务器·spring boot·后端
m0_748235953 小时前
【rustdesk】客户端和服务端的安装和部署(自建服务器,docker,远程控制开源软件rustdesk)
运维·服务器·docker
m0_748239333 小时前
Linux下C++轻量级WebServer服务器 框架梳理
linux·服务器·c++
Channing Lewis3 小时前
服务器广播算法
运维·服务器·算法
Dan淡淡的心3 小时前
软路由系统 iStoreOS 中部署 Minecraft 服务器
运维·服务器·docker·我的世界
吾与谁归in3 小时前
【C#设计模式(22)——策略模式(Stratege Pattern)】
设计模式·c#·策略模式
HaoHao_0103 小时前
实时计算Flink版
服务器·阿里云·云计算·云服务器