公用技术——设计模式16——行为型模式——备忘录模式

1、概念

备忘录模式记录对象的所有历史状态,这样做的目的是对象可以回滚到之前的任何一种历史状态。

备忘录模式涉及到三个角色

  • 核心对象:在对象的生命周期中,伴随着状态的改变。
  • 历史状态对象:它对应核心对象的某一个历史状态。
  • 历史状态管理对象:它用于执行保存,回溯历史状态等操作。

备忘录模式的示例随处可见,例如事务的回滚,电脑的撤销操作等。

2、UML图

  • CoreObject扮演着核心对象的角色,它拥有属性state。
  • History对象扮演着历史状态对象的角色,保存着某一个历史状态
  • HistoryManage对象扮演着历史状态管理对象的角色,用于保存,回溯历史状态等操作。

History对象可以拥有state属性,也可以把整个对象作为属性,需要注意的是CoreObject对象作为属性时,它保存的不是引用,而是对象本身。不要犯多个引用指向同一个CoreObject对象的错误

3、代码

3.1 CoreObject

/**
 * 
 * @File Name: CoreObject.java
 * @Description: 扮演者核心对象的角色,在其生命周期中会存在各种状态。
 * @version 1.0
 * @since JDK 1.8
 */
public class CoreObject {
	// 状态属性
	private String state;
	// get 和 set 省略
}

3.2 History

/**
 * 
 * @File Name: History.java
 * @Description: 对应CoreObject的某一种历史状态
 * @version 1.0
 * @since JDK 1.8
 */
public class History {
	// 这里也可以保存state属性,它是必备属性
	private CoreObject core;

	// private String state;
	public History(CoreObject core) {
		this.core = core;
	}
	
	// get 和 set 方法, 本质上不应该提供set方法,设置之后,不允许在修改。
}

3.3 HistoryManage

/**
 * 
 * @File Name: HistoryManage.java 
 * @Description: 扮演着管理历史状态的角色,执行保存,回滚等基本操作
 * @version 1.0
 * @since JDK 1.8
 */
public class HistoryManage {
	// 历史状态
	private static List<History> historys = new LinkedList<History>();

	public static void save(History history) {
		historys.add(history);
	}

	public static CoreObject revert(History history) {
		return history2core(history);
	}

	// 将核心对象转换为历史对象
	public static History core2History(CoreObject core) {
		return new History(core);
	}

	// 将历史对象转换为核心对象
	public static CoreObject history2core(History history) {
		return history.getCore();
	}
}

4、讨论

  问题1:History对象与CoreObject对象之间的关系?

  答:CoreObject对象与History对象是一种关联关系,1个CoreObject拥有多个History对象,每个History对象记录着CoreObject的一种历史状态。

  问题2:History对象有个数限制吗?

  答:在理论上History对象没有个数限制,但是在实际情况中,可以添加限制,因为过多的历史状态没有意义,而且会影响性能。

  当无限制时,建议在HistoryManage中使用LinkedList方式保存History对象,并限制只能回滚到前一种状态。因为链式结构在访问对象时,都需要遍历之前的对象,所以当History对象过多时,支持回滚到任意一种历史状态会影响性能。

  当有限制时,建议在HistoryManage中使用Stack方式保存History对象,并指定size为限制的个数。每次回滚使用stack的pop操作。

  问题3:保存的历史状态是否可以重复?

  答: 由核心对象决定。某些核心对象在生命周期中只有有限的几种状态,例如线程对象,它有就绪态,阻塞状态,运行状态,等待状态,死亡状态。某些操作会导致从一个状态转换为另外一种状态,但是这些状态是可以重复的,一个线程是可以多次进入阻塞状态的,而有些状态是不能重复的,例如死亡状态。

5、示例

  用户浏览网页的历史记录。

原文地址:https://www.cnblogs.com/rain144576/p/9940876.html