Java设计模式(十八)---备忘录模式

x33g5p2x  于2021-03-13 发布在 Java  
字(7.4k)|赞(0)|评价(0)|浏览(462)

 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将

该对象恢复到原先保存的状态。

一般模式:

Originator发起人角色
---|记录当前时刻的内部状态,负责定义那些属于备份范围的状态,负责创建和恢复备忘录数据
Memento备忘录角色
---|负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态
Caretaker备忘录管理员角色

---|对备忘录进行管理、保存和提供备忘录。

public class MementoTest {
	public static void main(String[] args) {
		//定义一个备忘录的发起者
		Originator origin = new Originator();
		origin.setState("你好!");
		//定义一个备忘录的管理者
		Caretaker care = new Caretaker();
		//创建一个备忘录
		care.setMemento(origin.createMemento());
		origin.setState("去死吧!");
		//恢复原有的数据
		origin.restoreMemento(care.getMemento());
		System.out.println(origin.getState());
	}
}
/**
 * 备忘录发起人的角色,
 * 备忘录中保存的就是该类的内容。
 * @author admin
 *
 */
class Originator{
	//一个String类型表示当前状态
	private String state = "";
	
	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
	//创建一个备忘录角色,用于时刻存储数据。
	public Memento createMemento(){
		return new Memento(this.state);
	}
	//回复原来的数据
	public void restoreMemento(Memento memento){
		this.setState(memento.getState());
	}
}
/**
 * 备忘录角色,
 * 该类用于备份、存储原有数据。
 * @author admin
 *
 */
class Memento{
	//一个String类型表示当前状态
	private String state = "";
	
	public Memento(String state) {
		this.state = state;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
}
/**
 * 备忘录的管理类
 * 对备忘录进行管理、保存和存储
 * @author admin
 */
class Caretaker{
	private Memento memento;

	public Memento getMemento() {
		return memento;
	}

	public void setMemento(Memento memento) {
		this.memento = memento;
	}
}

一个例子:

模拟月光宝盒中,至尊宝阻止白晶晶自杀的桥段。当白晶晶在洞内自杀,至尊宝没有来得及救,于是就使用月光宝盒--菠萝菠萝蜜
任何就回到上一个状态,继续去救白晶晶,知道能够成功救到为止。
这个例子可以说明,救白晶晶之前,首先保存一个状态命名为1,从这一状态出发,如果没有成功,就回到1状态。

public class MementoT {
	public static void main(String[] args) {
		//创建一个发起者,(看见白晶晶在自杀)
		SaveLifeAction action = new SaveLifeAction();
		action.setState("白晶晶被至尊宝伤透了心...准备拿剑抹脖子自杀");
		//月关宝盒时刻记录每一瞬间
		BoxManager boxManager = new BoxManager();
		boxManager.setBoxMemento(action.createMemento());
		action.setState("白晶晶自杀死了...");
		System.out.println(action.getState());
		System.out.println("---至尊宝拿着月关宝盒,回去救她----");
		//至尊宝拿着月关宝盒,回去救她
		action.restoreMemento(boxManager.getBoxMemento());
		//回到上一状态
		System.out.println(action.getState());
		action.setSuccess(true);
		if(action.isSuccess()){
			System.out.println("----白晶晶成功获救!");
		}
	}
}
/**
 * 该类是发起者类,
 * 设置负责创建和恢复备忘录
 * @author admin
 *
 */
class SaveLifeAction{
	//定义一个状态,用于描述当前正在做什么..
	private String  state="";
	//设置是否救成功
	private boolean isSuccess;
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
	public boolean isSuccess() {
		return isSuccess;
	}
	public void setSuccess(boolean isSuccess) {
		this.isSuccess = isSuccess;
	}
	//创建一个备份的状态
	public BoxMemento createMemento(){
		return new BoxMemento(this.state);
	}
	//恢复到原来的状态
	public void restoreMemento(BoxMemento boxMemento){
		this.setState(boxMemento.getState());
	}
}
/**
 * 该类是备忘录类
 * 相当于故事中的月光宝盒,他带你回到上一个状态。
 * 内部实现的原理就是,保存上一状态而已。
 * @author admin
 *
 */
class BoxMemento{
	private String state="";

	public BoxMemento(String state) {
		this.state = state;
	}
	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
}
/**
 * 备忘录的管理者,
 * 谁拿到月光宝盒,谁就可以操纵月光宝盒,
 * 就可以回到过去。
 * @author admin
 *
 */
class BoxManager{
	
	private BoxMemento boxMemento;

	public BoxMemento getBoxMemento() {
		return boxMemento;
	}

	public void setBoxMemento(BoxMemento boxMemento) {
		this.boxMemento = boxMemento;
	}
}

备忘录模式的使用场景
---|需要保存和恢复数据的相关状态场景。
---|提供一个可回滚(rollback)的操作,比如word中Ctrl+Z的组合键。
---|需要监控的副本场景中。
---|数据库连接的事务管理就是用的备忘录模式。

备忘录的扩展

---|1、实现java类中的Cloneable实现备忘录模式
     使用clone方式的备忘录模式,可以使用在比较简单的场景或者比较单一的场景中,
     尽量不要与其他的对象产生严重的耦合关系。

public class MementoExpand {
	public static void main(String[] args) {
		//定义一个发起人
		OriginClass origin = new OriginClass();
		origin.setState("我的原始状态");
		//创建备份
		origin.createOrigin();
		origin.setState("我的现在状态..");
		System.out.println(origin.getState());
		System.out.println("------我不喜欢现在的状态-------");
		//恢复原来的状态
		origin.restoreOrigin();
		System.out.println(origin.getState());
	}
}
/**
 * 发起者实现Cloneable接口,完成自身的备忘录设置。
 * 无需接触其他类来保存自身的当前状态。
 * @author admin
 *
 */
class OriginClass implements Cloneable{
	private String state;
	//自身的备忘录角色
	private OriginClass backUp;
	
	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
	//创建备份
	public void createOrigin(){
		this.backUp = (OriginClass) this.clone();
	}
	//恢复原来的信息
	public void restoreOrigin(){
		this.setState(backUp.getState());
	}
	
	@Override
	protected Object clone() {
		try {
			return (OriginClass) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}

---|2多状态的备忘录模式

/**
 * 通过java.beans.Introspector类获取其他类中的属性和方法
 * @author admin
 *
 */
public class BeanUtil {
	public static void main(String[] args) {
		//创建一个发起者
		MyOringin origin = new MyOringin("lzl",10000,"程序员");
		System.out.println("在百度公司里:"+origin.toString());
		//在百度公司创建备份
		MyMementor mementor = origin.createMemento();
		System.out.println("感觉太累了,跳槽的阿里巴巴...");
		origin.setName("lzl");
		origin.setPosition("程序员");
		origin.setSalary(12000);
		System.out.println("跳槽到阿里:"+origin.toString());
		System.out.println("----------------在这里更累,跟着老大,10天没合眼...想回到百度了.");
		origin.restoreMemento(mementor);
		System.out.println("回到百度,还是很轻松的。。"+origin.toString());
		
	}
	//获取发起者类中的属性参数,并保存在hashMap中
	public static HashMap<String, Object> backUpProp(Object bean){
		HashMap<String, Object> result = new HashMap<String, Object>();
		//获得Bean描述
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
			//返回PropertyDescriptor类型的javaBean描述
			PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
			//遍历返回的javaBean
			for(PropertyDescriptor des : descriptors){
				String fieldName = des.getName();
				//读取属性的方法
				Method getter = des.getReadMethod();
				//读取属性值
				Object fieldValue = getter.invoke(bean, new Object[]{});
				if(!fieldName.equalsIgnoreCase("class")){
					result.put(fieldName, fieldValue);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	//把HashMap中的值设置到bean中。
	public static void restoreProp(Object bean,HashMap<String, Object> propMap){
		//获取BeanInfo
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
			//获取PropertyDescriptor的对象数组
			PropertyDescriptor[] descripors = beanInfo.getPropertyDescriptors();
			//增强for循环,遍历所有的属性,设置到bean中
			for(PropertyDescriptor des : descripors){
				//获取key值对象
				String fieldName = des.getName();
				//如果包含这个属性
				if(propMap.containsKey(fieldName)){
					//获取属性set的方法
					Method setter = des.getWriteMethod();
					setter.invoke(bean, new Object[]{propMap.get(fieldName)});
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * 类的发起者,模拟拥有多个属性。
 * @author admin
 *
 */
class MyOringin{
	//姓名
	private String name;
	//薪水
	private double salary;
	//职位
	private String position;
	
	public MyOringin(String name,double salary,String position) {
		this.name = name;
		this.salary = salary;
		this.position = position;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public String getPosition() {
		return position;
	}
	public void setPosition(String position) {
		this.position = position;
	}
	//创建一个备份
	public MyMementor createMemento(){
		//将方法属性存储到BeanUtil.backUpProp()中的hashMap中
		return new MyMementor(BeanUtil.backUpProp(this));
	}
	public void restoreMemento(MyMementor memento){
		BeanUtil.restoreProp(this, memento.getBeanMap());
	}
	@Override
	public String toString() {
		return "姓名:"+this.name+"\t职位:"+this.position
				+"\t薪水:"+this.salary+"\t";
	}
}
/**
 * 备忘录类,用于保存原有的状态。
 * @author admin
 */
class MyMementor{
	//定义一个hashMap来接收发起者的所有属性状态备份
	private HashMap<String, Object> beanMap = new HashMap<String, Object>();
	
	public MyMementor(HashMap<String, Object> beanMap) {
		this.beanMap = beanMap;
	}

	public HashMap<String, Object> getBeanMap() {
		return this.beanMap;
	}

	public void setBeanMap(HashMap<String, Object> beanMap) {
		this.beanMap = beanMap;
	}
}

相关文章