设计模式--备忘录模式

简介

​ 备忘录模式(Memento Pattern)又称为快照模式(Snapshot Pattern)或令牌模式(Token Pattern),是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态,属于行为型模式。

​ 在软件系统中,备忘录模式可以为我们提供一种“后悔药”的机制,他通过存储系统各个历史状态的快照,使得我们可以在任意时刻将系统回滚到某一个历史状态。

​ 备忘录模式本质是从发起人实体类(Originator)隔离存储功能,降低实体类的职责。同时由于存储信息(Memento)独立,且存储信息的实体交由管理类(Caretaker)管理,则可以通过为管理类扩展额外的功能对存储信息进行扩展操作(比如增加历史快照功能)。

备忘录模式的生活场景

1、git的版本管理

2、游戏的存档

备忘录模式适用于以下应用场景:

1、需要保存历史快照的场景;

2、希望在对象之外保存状态,且除了自己其他类对象无法访问状态保存具体内容。

备忘录模式的通用UML类图:

从UML类图中,我们可以看到,备忘录模式主要包含三种角色:

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

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

备忘录管理角色(Caretaker):负责存储,提供管理备忘录(Memento),无法对备忘录内容进行操作和访问。

备忘录模式在源码中的体现

备忘录模式在框架源码中的应用比较少,主要还是需要结合具体的业务场景来使用。

Spring的webflow源码中StateManageableMessageContext接口

public interface StateManageableMessageContext extends MessageContext {

	Serializable createMessagesMemento();

	void restoreMessages(Serializable messagesMemento);

	void setMessageSource(MessageSource messageSource);
}

可以看到这里有一个createMessagesMemento()方法,创建一个消息备忘录。它的实现类:

public class DefaultMessageContext implements StateManageableMessageContext {

	private static final Log logger = LogFactory.getLog(DefaultMessageContext.class);

	private MessageSource messageSource;

	@SuppressWarnings("serial")
	private Map<Object, List<Message>> sourceMessages = new AbstractCachingMapDecorator<Object, List<Message>>(
			new LinkedHashMap<Object, List<Message>>()) {

		protected List<Message> create(Object source) {
			return new ArrayList<>();
		}
	};
    
    ...

	public void clearMessages() {
		sourceMessages.clear();
	}

	// implementing state manageable message context

	public Serializable createMessagesMemento() {
		return new LinkedHashMap<Object, List<Message>>(sourceMessages);
	}

	@SuppressWarnings("unchecked")
	public void restoreMessages(Serializable messagesMemento) {
		sourceMessages.putAll((Map<Object, List<Message>>) messagesMemento);
	}

	public void setMessageSource(MessageSource messageSource) {
		if (messageSource == null) {
			messageSource = new DefaultTextFallbackMessageSource();
		}
		this.messageSource = messageSource;
	}
    ...
}

我们看到其主要逻辑就相当于是给Message留一个备用,以备恢复之用。

备忘录模式的优缺点

优点:

1、简化发起人实体类(Originator)职责,隔离状态存储或获取,实现了信息的封装,客户端无需关心状态的保存细节;

2.提供状态回滚功能;

缺点:

消耗资源:如果需要保存的状态过多时,每一次保存都会消耗很多内存。

代码链接

备忘录模式

posted @ 2021-07-26 22:51  snail灬  阅读(177)  评论(0编辑  收藏  举报