JAVA中的备忘录模式实例教程

简介:

原文链接  作者:Pankaj Kumar 译者:f0tlo <1357654289@qq.com>

备忘录模式是一种行为模式。备忘录模式用于保存对象当前状态,并且在之后可以再次使用此状态。备忘录模式实现的方式需要保证,被保存的对象状态不能被对象从外部访问,目的为了被保存的这些对象状态的完整性。

备忘录模式通过两个对象实现:Originator以及Caretaker。Originator类代表了其状态能够被存储并被用于恢复之前的状态,它使用内部类保存对象的状态。此内部类就被叫做备忘录,注意此类是私有的,它不能被其他对象访问。

Caretaker是一个帮助类,它的职责就是通过备忘录帮助Originator存储当前状态或者恢复重建其之前的状态。因为备忘录是Originator的私有类,Caretaker不能访问它,因此它作为一个对象被存储在caretaker中。

现实中最好的例子是文本编辑器,它任何时候都存在已经输入的数据,并且可以使用回退功能恢复之前的存储(写作)状态。我们将实现相同功能并且提供一个任何时候都把输入、存在内容到文件中的工具集,此外,我们也能恢复上一个存储(写作)的状态。为了简单,此处没用更实用任何写入数据到文件的IO操作。

Originator类


package com.journaldev.design.memento;

public class FileWriterUtil {

	private String fileName;
	private StringBuilder content;

	public FileWriterUtil(String file){
		this.fileName=file;
		this.content=new StringBuilder();
	}

	@Override
	public String toString(){
		return this.content.toString();
	}

	public void write(String str){
		content.append(str);
	}

	public Memento save(){
		return new Memento(this.fileName,this.content);
	}

	public void undoToLastSave(Object obj){
		Memento memento = (Memento) obj;
		this.fileName= memento.fileName;
		this.content=memento.content;
	}

	private class Memento{
		private String fileName;
		private StringBuilder content;

		public Memento(String file, StringBuilder content){
			this.fileName=file;
			//notice the deep copy so that Memento and FileWriterUtil content variables don't refer to same object
			this.content=new StringBuilder(content);
		}
	}
}


注意备忘录的内部类及其保存及恢复方法。现在实现Caretaker类

Caretaker类


package com.journaldev.design.memento;

public class FileWriterCaretaker {

	private Object obj;

	public void save(FileWriterUtil fileWriter){
		this.obj=fileWriter.save();
	}

	public void undo(FileWriterUtil fileWriter){
		fileWriter.undoToLastSave(obj);
	}
}


注意caretaker对象包含了整个对象形式的存储状态,因此它既不能修改被保存对象又对其结构未知。

备忘录测试类

完整一个简单地测试程序


package com.journaldev.design.memento;

public class FileWriterClient {

	public static void main(String[] args) {

		FileWriterCaretaker caretaker = new FileWriterCaretaker();

		FileWriterUtil fileWriter = new FileWriterUtil("data.txt");
		fileWriter.write("First Set of Data\n");
		System.out.println(fileWriter+"\n\n");

		// lets save the file
		caretaker.save(fileWriter);
		//now write something else
		fileWriter.write("Second Set of Data\n");

		//checking file contents
		System.out.println(fileWriter+"\n\n");

		//lets undo to last save
		caretaker.undo(fileWriter);

		//checking file content again
		System.out.println(fileWriter+"\n\n");

	}

}


上述程序的输出如下:


First Set of Data

First Set of Data
Second Set of Data

First Set of Data


此模式简单易实现,但是需要注意的是备忘录类只能被Originator对象访问。在客户端程序中,使用caretaker对象完成保存或恢复originator对象的状态。

另外,如果Originator对象有一些属性不是不可变的,我们需要使用深拷贝或者克隆来避免数据的完整性问题。使用序列化来取得备忘录模式的实现不失为一般方法,而不是为每一个对象创建一个自己的备忘录实现。

此模式的缺点是, 如果Originator对象非常巨大,那么备忘录对象的大小也会被相应增大,因而需要更多的内存空间。

目录
相关文章
|
23天前
|
Java 开发者 UED
【实战宝典】Java异常处理大师级教程:throws关键字,让异常声明成为你的专属标签!
【实战宝典】Java异常处理大师级教程:throws关键字,让异常声明成为你的专属标签!
36 3
|
5天前
|
Java
Java——接口的使用实例
Comparable接口用于自定义类的对象比较。通过实现此接口并重写`compareTo`方法,可以定义自定义类型的比较规则。 接下来介绍了Comparator接口,它提供了一种更灵活的比较方式。通过实现Comparator接口并重写`compare`方法,可以根据不同属性定义不同的比较规则。例如,定义一个`BrandComparator`类来比较汽车的品牌。 最后,介绍了Cloneable接口,用于实现对象的克隆。实现该接口并重写`clone`方法后,可以创建对象的浅拷贝或深拷贝。浅拷贝仅复制对象本身,深拷贝则会递归复制所有成员变量。
12 4
Java——接口的使用实例
|
6天前
|
存储 Java
Java内置数据类型和实例的详解
Java内置数据类型分为基本和引用两类。基本数据类型包括整型(`byte`、`short`、`int`、`long`)、浮点型(`float`、`double`)、字符型(`char`)和布尔型(`boolean`),用于存储简单的数值;引用数据类型则用于存储对象的引用,包括类(如`String`)、接口和数组。掌握这两类数据类型是Java编程的基础。以下示例展示了各种数据类型的使用方法。
|
1天前
|
Java API
Java时间戳教程
本文详细介绍Java中时间戳的处理方法,包括获取当前时间戳、使用`java.time`包、时间戳与日期的相互转换及格式化等。示例代码展示了如何利用`System.currentTimeMillis()`和`java.time.Instant`获取时间戳,以及如何通过`Date`和`ZonedDateTime`进行日期转换和时区处理。随着Java 8引入的`java.time`包,日期时间操作变得更加强大和便捷,推荐在新项目中优先采用。
|
8天前
|
Java
Java实例详解
Java实例是通过类创建的对象,其核心在于将抽象的类定义转化为具体的实体。类作为对象的模板定义了属性和行为,而实例则是这些定义的具体实现。通过`new`关键字可以创建实例,并利用点运算符访问其属性和方法。实例拥有自己的生命周期,从创建到使用直至被垃圾回收机制自动清理。此外,实例变量和静态变量的区别在于前者属于单个实例,后者则为所有实例共享。理解Java实例的概念及其管理对编程至关重要。
|
1月前
|
Java
【Java基础面试七】、请介绍一下实例变量的默认值
这篇文章介绍了Java中实例变量的默认值:引用数据类型的默认值是null,而基本数据类型的默认值根据其类型分别是0、0L、0.0F、0.0、'\u0000'和false。
【Java基础面试七】、请介绍一下实例变量的默认值
|
1月前
|
前端开发 Java Maven
【前端学java】全网最详细的maven安装与IDEA集成教程!
【8月更文挑战第12天】全网最详细的maven安装与IDEA集成教程!
66 2
【前端学java】全网最详细的maven安装与IDEA集成教程!
|
25天前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
24天前
|
Java 开发者
Java多线程教程:使用ReentrantLock实现高级锁功能
Java多线程教程:使用ReentrantLock实现高级锁功能
23 1
|
1月前
|
存储 网络协议 Oracle
java教程
java教程【8月更文挑战第11天】
23 5