备忘录设计模式 学习笔记

本文详细介绍了备忘录模式的概念及其在文本编辑器中的应用,通过Java实例展示了如何使用备忘录模式保存和恢复对象状态。备忘录模式在Git、SVN等版本控制系统中也得到广泛应用。文章还提到了深拷贝在确保数据完整性方面的重要性,并探讨了使用序列化实现更通用的备忘录模式的可能性,以及在大数据量时可能存在的内存消耗问题。最后,生活中的例子——文本编辑器的撤销功能进一步解释了备忘录模式的实际运用。
摘要由CSDN通过智能技术生成

GoF原文
Without violating encapsulation,capture and externalize an object’s internal state so that the object can be restored to this state later.

Memento design pattern is used when we want to save the state of an object so that we can restore later on.
在这里插入图片描述

备忘录模式的应用场景

对于程序员来说,可能天天都在使用备忘录模式,比如我们每天使用的Git、SVN都可以提供一种代码版本撤回的功能。
还有一个比较贴切的现实场景就是游戏的存档功能,通过将游戏当前进度存储到本地文件系统或数据库中,使得下次继续游戏时,玩家可以从之前的位置继续进行。

备忘录模式主要适用于以下应用场景。
(1)需要保存历史快照的场景。
(2)希望在对象之外保存状态,且除了自己,其他类对象无法访问状态保存的具体内容。
在这里插入图片描述

Originator is the object whose state needs to be saved and restored and it uses an inner class to save the state of Object. The inner class is called Memento and it’s private, so that it can’t be accessed from other objects.

Caretaker is the helper class that is responsible for storing and restoring the Originator’s state through Memento object. Since Memento is private to Originator, Caretaker can’t access it and it’s stored as an Object within the caretaker.

Originator Class

[ 美 /əˈrɪdʒɪneɪtər/] 创始人

public class A1_FileWriterUtil {

	private String fileName;
	private StringBuilder content;
	
	public A1_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);
		}
	}
}

个人理解:
save 就是:创建一个Memeto对象,把当前对象状态存储到Memeto对象里,返回Memeto对象到外面储存起来
undoToLastSave就是:把储存的Memeto对象拿进来,把当前对象的状态换成Memeto对象储存的值。
Caretaker 就是干存储Memeto对象,提供Memeto对象的活

Caretaker Class

[ 美 /ˈkerteɪkər/] 守护者

public class A2_FileWriterCaretaker {

	private Object obj;
	
	public void save(A1_FileWriterUtil fileWriter){
		this.obj=fileWriter.save();
	}
	
	public void undo(A1_FileWriterUtil fileWriter){
		fileWriter.undoToLastSave(obj);
	}
}

Example Test Class

	public static void main(String[] args) {
		
		A2_FileWriterCaretaker caretaker = new A2_FileWriterCaretaker();
		
		A1_FileWriterUtil fileWriter = new A1_FileWriterUtil("data.txt");
		
		fileWriter.write("First Set of Data ");
		System.out.println(fileWriter);
		// lets save the file
		caretaker.save(fileWriter);
		
		//now write something else
		fileWriter.write("Second Set of Data ");
		//checking file contents
		System.out.println(fileWriter);

		//lets undo to last save
		caretaker.undo(fileWriter);
		//checking file content again
		System.out.println(fileWriter);
	}

结果

First Set of Data 
First Set of Data Second Set of Data 
First Set of Data 

if Originator object has properties that are not immutable, we should use deep copy or cloning to avoid data integrity issue like I have used in above example.
如果Originator对象的属性是可变的,我们应该使用deep copy或cloning 来避免数据完整性问题,就像我在上面的例子中使用的那样。

We can use Serialization to achieve memento pattern implementation that is more generic rather than Memento pattern where every object needs to have it’s own Memento class implementation.
我们可以使用序列化来实现更通用的memento模式实现,而不是每个对象都需要有自己的memento类实现的memento模式。

One of the drawback is that if Originator object is very huge then Memento object size will also be huge and use a lot of memory.
缺点之一是,如果Originator对象非常大,那么Memento对象的大小也会非常大,并使用大量内存。

在这里插入图片描述
备忘录模式生活中的例子:
一个最好的现实例子是文本编辑器,我们可以随时保存它的数据,并使用撤销来恢复它到以前保存的状态。

在JDK源码里一顿找,目前为止还是没找到具体的应用,包括在MyBatis中也没有找到对应的源码。在Spring的Webflow源码中找到一个StateManageableMessageContext接口

public interface StateManageableMessageContext extends MessageContext {
 
    public Serializable createMessagesMemento();
 
    public void restoreMessages(Serializable messagesMemento);
 
    public void setMessageSource(MessageSource messageSource);
}

我们看到有一个createMessagesMemento()方法,创建一个消息备忘录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值