二十三种设计模式第二十篇--备忘录模式

备忘录模式,备忘录模式属于行为型模式。它允许在不破坏封装的情况下捕获和恢复对象的内部状态。保存一个对象的某个状态,以便在适当的时候恢复对象,该模式通过创建一个备忘录对象来保存原始对象的状态,并将其存储在一个负责管理备忘录的负责人对象中。

备忘录模式的核心组成部分包括:

发起人(Originator):负责创建备忘录对象,并在需要的时候将自身状态保存到备忘录中。

备忘录(Memento):用于存储发起人对象的内部状态。

负责人(Caretaker):负责管理备忘录对象,可以对备忘录进行保存、恢复或删除等操作。

备忘录模式的优点包括:

  1. 封装了状态保存和恢复的细节:备忘录模式将保存和恢复对象状态的逻辑封装在备忘录对象中,发起人对象无需关心其具体实现。
  2. 支持撤销操作:通过存储历史状态的备忘录对象,可以轻松实现对象的撤销操作。
  3. 简化了原发器类:发起人对象只需关注自身的核心功能,而状态保存和恢复的责任交给备忘录和负责人对象。

备忘录模式也有一些限制和适用场景:

  • 消耗内存:如果发起人对象的状态非常大或者频繁保存状态,可能会占用大量的内存空间。
  • 额外开销:备忘录模式会引入额外的对象用于保存和管理状态,可能增加系统的开销。

其应用实例:

1、浏览器回退,前进

2、数据库备份与还原

3、Git版本管理

4、棋牌游戏悔棋

  1. 编辑器当前 undo,redo.

使用场景:

1、需要保存/恢复数据的相关状态场景。

2、提供一个可回滚的操作。

java 复制代码
/**
 * 发起人(Originator)角色:
 *     记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息
 */
public class Originator {
   private String state;
 
   public void setState(String state){
      this.state = state;
   }
 
   public String getState(){
      return state;
   }

   /**
    * 生成一个备忘录对象
    * @return
    */
   public Memento saveStateToMemento(){
      //TODO:  .....将状态信息包装进去.
      return new Memento(state);
   }

   /**
    * 恢复关态
    * @param Memento
    */
   public void getStateFromMemento(Memento Memento){
      //TODO:....从memento对象取出所有的状态进行恢复.
      state = Memento.getState();
   }
}
java 复制代码
/**
 * 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
 */
public class CareTaker {
   //TODO:也可以是一个栈来保存.
   private List<Memento> mementoList = new ArrayList<Memento>();
 
   public void add(Memento state){
      mementoList.add(state);
   }

   /**
    * 获取第几步的状态信息
    * @param index
    * @return
    */
   public Memento get(int index){
      return mementoList.get(index);
   }

   /**
    * 出栈操作
    * @return
    */
   public Memento pop(){
      Memento last=mementoList.get(      mementoList.size()-1 );
      if( last!=null ) {
         mementoList.remove(last);
      }
      return last;
   }
}
java 复制代码
/**
 * 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
 */
public class Memento {
   //TODO:要保存的状态信息
   private String state;
 
   public Memento(String state){
      this.state = state;
   }
 
   public String getState(){
      return state;
   }  
}
java 复制代码
/**
 * 测试类
 */
public class MementoPatternDemo {
   public static void main(String[] args) {
      //创建发起人(Originator)角色: 生成要保存的备忘的对象
      Originator originator = new Originator();
      //创建管理者(Caretaker):保存的列表
      CareTaker careTaker = new CareTaker();

      //记录状态
      originator.setState("State #1");  //#1的状态没有保存
      originator.setState("State #2");
      //保存状态
      careTaker.add(   originator.saveStateToMemento());  //只保存了#2状态.
      originator.setState("State #3");
      careTaker.add(originator.saveStateToMemento());
      originator.setState("State #4");
 
      System.out.println("当前状态: " + originator.getState());  //#4

      originator.getStateFromMemento(careTaker.get(0));
      System.out.println("取保存好的第一个状态:  " + originator.getState());  // #2

      originator.getStateFromMemento(careTaker.get(1));
      System.out.println("取保存好的第二个状态: " + originator.getState());  // #3
   }
}

注意事项:

1、为了符合迪米特原则,还要增加一个管理备忘录的类。

2、为了节约内存,可使用原型模式+备忘录模式。

相关推荐
天天摸鱼的java工程师5 分钟前
设计一个支持千万级用户的 IM 系统:消息推送如何保证可靠性
java·后端
天天摸鱼的java工程师27 分钟前
秒杀系统中:如何防止超卖和库存超扣?
java·后端
CodeCipher35 分钟前
Java基础复习之继承
java·开发语言
BillKu42 分钟前
Java延时
java·开发语言
啾啾Fun1 小时前
Java面试题:分布式ID时钟回拨怎么处理?序列号耗尽了怎么办?
java·分布式·分布式id·八股
qq_534452521 小时前
【算法 day02】LeetCode 209.长度最小的子数组 | 59.螺旋矩阵II
java·算法·leetcode·职场和发展
向上的车轮1 小时前
语言特性适用的场景:卫星、火箭控制系统用什么开发语言?
java·开发语言·c++·c#·c·ada
zhendeWD1 小时前
springboot项目启动报错:spring boot application in default package
java·spring boot·后端
风象南2 小时前
SpringBoot实现6种JWT令牌失效方案
java·spring boot·后端
llwszx2 小时前
“从HTTP到TCP/IP的旅程“-----深入浅出Java Web通信
java·websocket·网络协议·tcp/ip·spring·http