Java设计模式之备忘录模式

作者:tianClassmate 时间:2023-08-24 06:17:05 

无论是我们在使用word还是记事本,系统都会为我们提供撤销的功能,这几乎是人人都会使用到的功能,而在我们实际开发中,会不会存在一个很复杂的对象,当更改了其中的某一个属性以后,也提供撤销的功能,可以快速恢复到更新前的状态。提供该功能的模式也正是今天的主题——备忘录模式。

一、概念理解

书上备忘录的解释是,在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

其实也就是在一个对象之外再额外的增加一个副本对象,每当我们在对象上更改一些属性以后就构建一个副本,并把副本存放在一个队列中,每当回退该对象的时候就从副本中恢复数据。

很显然需要三个角色:原对象、副本对象、存放副本的队列。

也即书上的三个角色定义:

Originator(发起人角色):负责创建一个备忘录,记录自身需要保存的状态,具备状态回滚功能;即原对象。

Memento(备忘录角色):用于存储Originator的内部状态,且可以防止Originator以外的对象进行访问;即副本对象。

Caretaker(管理员角色):负责存储、提供管理Memento,无法对Memento的内容进行操作和访问;也即存放副本的队列。

为了让概念落地,我们基于备忘录模式的思想实现视频草稿箱的功能。

在这个业务场景中,发起人其实就是编辑视频的编辑器,在这个编辑器中我们能干啥呢?编辑视频、从草稿箱导入、保存到草稿箱。这不是就是发起人角色的作用吗!我们称为编辑草稿。

备忘录那不就是草稿修改后吗,我们称之为完稿。

完稿做好了,要存放到一个列表中用于我们快速修复,那当然就是管理员角色。

基于三个角色我们实现代码。

二、案例实现

备忘录角色(完稿):

就是个基础对象,用于存储数据,视频包含的属性主要是,标题、封面、视频地址

/**
* 备忘录(完稿)
* @author tcy
* @Date 16-09-2022
*/
public class VideoMemento {
   private String title;
   private String videoUrl;
   private String imgs;

public VideoMemento(String title, String content, String imgs) {
       this.title = title;
       this.videoUrl = content;
       this.imgs = imgs;
   }

public String getTitle() {
       return title;
   }

public String getContent() {
       return videoUrl;
   }

public String getImgs() {
       return imgs;
   }

@Override
   public String toString() {
       return "ArticleMemento{" +
               "title='" + title + '\'' +
               ", content='" + videoUrl + '\'' +
               ", imgs='" + imgs + '\'' +
               '}';
   }
}

发起人角色(编辑草稿):

在基本对象之上,增加保存和撤销的操作,可以看到和我们定义的完稿长的一样,只是又增了saveToMemento()方法和undoFromMemento()方法,用于保存和撤销。

/**
* 发起人 (草稿)
* @author tcy
* @Date 16-09-2022
*/
public class Editor {
   private String title;
   private String videoUrl;
   private String imgs;

public Editor(String title, String videoUrl, String imgs) {
       this.title = title;
       this.videoUrl = videoUrl;
       this.imgs = imgs;
   }

public String getTitle() {
       return title;
   }

public String getContent() {
       return videoUrl;
   }

public String getImgs() {
       return imgs;
   }

public void setTitle(String title) {
       this.title = title;
   }

public void setContent(String content) {
       this.videoUrl = content;
   }

public void setImgs(String imgs) {
       this.imgs = imgs;
   }

/**
    *  保存到备忘录
    * @return
    */
   public VideoMemento saveToMemento(){
       VideoMemento articleMemento = new VideoMemento(this.title,this.videoUrl,this.imgs);
       return articleMemento;
   }

/**
    * 从备忘录恢复
    * @param articleMemento
    */
   public void undoFromMemento(VideoMemento articleMemento){
       this.title = articleMemento.getTitle();
       this.videoUrl = articleMemento.getContent();
       this.imgs = articleMemento.getImgs();
   }

@Override
   public String toString() {
       return "Editor{" +
               "title='" + title + '\'' +
               ", content='" + videoUrl + '\'' +
               ", imgs='" + imgs + '\'' +
               '}';
   }
}

管理员角色(草稿箱):

包括一个栈,用于存储完稿,利用栈先进后出的特性,实现逐步的撤销。

/**
* 管理者(草稿箱)
* @author tcy
* @Date 16-09-2022
*/
public class Caretaker {
   private final Stack<VideoMemento> STACK = new Stack<VideoMemento>();

public VideoMemento getMemento(){
       VideoMemento videoMemento = STACK.pop();
       return videoMemento;
   }

public void addMemento(VideoMemento videoMemento){
       STACK.push(videoMemento);
   }
}

读者可以拉取完整代码到本地进行学习,实现代码均测试通过后上传到码云,本地下载。

三、总结

备忘录模式是怎么回事想必你已经明白了,如果我们在实际开发中有一个对象的功能很复杂,属性非常的多,这时候备忘录模式就是一个好的选择。

备忘录模式实现也很简单,在原对象基础之上再增加一个副本对象,在原对象上额外的增加两个方法,用于构建一个副本和从副本中取值。再创建一个栈对象,用于存储、管理副本。

备忘录模式的优势突出,会简化发起人(原对象)的职责,隔离存储状态,实现信息的封装,客户端无须关心保存细节,而且提供了状态回滚功能。

但是最显著的缺点就是消耗资源,如果对象改动较大,每一次保存都会消耗很大的内存空间,功能换空间。

备忘录模式在Jdk和Spring中应用的并不多,在我们实际应用中我们要衡量空间和效率的影响,是否使用备忘录模式进行合理的取舍。

来源:https://www.cnblogs.com/tianClassmate/p/16706597.html

标签:Java,设计,备忘录,模式
0
投稿

猜你喜欢

  • Android AlertDialog的几种用法详解

    2023-12-02 18:15:50
  • Java日常练习题,每天进步一点点(58)

    2021-06-26 01:13:02
  • 轻松实现Rxjava定时器功能

    2022-03-12 06:23:27
  • android自定义WaveView水波纹控件

    2023-08-25 21:09:47
  • Android实现声音采集回声与回声消除

    2022-09-28 12:13:17
  • Spring超详细讲解创建BeanDefinition流程

    2023-11-25 08:37:55
  • Android自定义ProgressDialog进度等待框

    2022-07-09 13:51:46
  • AlertDialog点击按钮不消失的实现方法

    2023-12-12 07:11:16
  • WPF自定义控件和样式之自定义按钮(Button)

    2022-04-09 14:39:32
  • Java语言实现数据结构栈代码详解

    2021-12-09 16:15:05
  • 基于Java数组实现循环队列的两种方法小结

    2023-06-30 16:09:01
  • 解析spring加载bean流程的方法

    2023-11-29 13:50:32
  • C# 多线程编程技术基础知识入门

    2023-05-27 08:00:24
  • 一文带你全面了解Java Hashtable

    2021-09-19 01:39:39
  • java Class.getSimpleName() 详解及用法

    2021-06-26 16:35:41
  • Java实现简单员工管理系统

    2021-12-13 17:51:26
  • idea使用外置tomcat配置springboot详细步骤

    2023-11-20 03:56:49
  • Java后端学习精华之TCP通信传输协议详解

    2021-08-06 03:15:42
  • 详解Android性能优化之启动优化

    2023-07-16 06:00:07
  • C语言与C++中关于字符串使用的比较

    2022-01-22 01:30:37
  • asp之家 软件编程 m.aspxhome.com