现在的位置: 首页 > 综合 > 正文

备忘录模式(Memento)

2013年02月06日 ⁄ 综合 ⁄ 共 3043字 ⁄ 字号 评论关闭

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

@@@练习示例: 
仿真系统

@@@示例代码:
\pattern\FlowAMockMemento.java

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 模拟运行流程A的对象的备忘录接口,是个窄接口
 */
public interface FlowAMockMemento {
    // 空的
}

\pattern\FlowAMock.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 模拟运行流程A,只是一个示意,代指某个具体流程
 */
public class FlowAMock {
    /**
     * 流程名称,不需要外部存储的状态数据
     */
	private String flowName;
	
	/**
	 * 示意,代指某个中间结果,需要外部存储的结果数据
	 */
	private int tempResult;
	
	/**
	 * 示意,代指某个中间状态,需要外部存储的状态数据
	 */
	private String tempState;
	
	/**
	 * 构造方法,传入流程名称
	 * @param flowName 流程名称 
	 */
	public FlowAMock(String flowName) {
		this.flowName = flowName;
	}
	
	/**
	 * 示意,运行流程的第一个阶段
	 */
	public void runPhaseOne() {
		// 在这个阶段,可能产生了中间结果,示意一下
		tempResult = 6;
		tempState = "PhaseOne";
	}
	
	/**
	 * 示意,按照方案一来运行流程后半部分
	 */
	public void schema1() {
		// 示意,需要使用第一个阶段产生的数据
		this.tempState += ", Schema1";
		System.out.println(flowName + " " + this.tempState + 
				" : now run " + tempResult);
		this.tempResult += 11;
	}
	
	/**
	 * 示意,按照方案二来运行流程后半部分
	 */
	public void schema2() {
		// 示意,需要使用第一个阶段产生的数据
		this.tempState += ", Schema2";
		System.out.println(flowName + " " + this.tempState + 
				" : now run " + tempResult);
		this.tempResult += 22;
	}
	
	/**
	 * 真正的备忘录对象,实现备忘录窄接口
	 * 实现成私有的内部类,不让外部访问
	 */
	private static class MementoImpl implements FlowAMockMemento {
		/**
		 * 示意,保存某个中间结果
		 */
		private int tempResult;
		
		/**
		 * 示意,保存某个中间状态
		 */
		private String tempState;
		
		public MementoImpl(int tempResult, String tempState) {
			this.tempResult = tempResult;
			this.tempState = tempState;
		}

		public int getTempResult() {
			return tempResult;
		}

		public String getTempState() {
			return tempState;
		}
	}
	
	/**
	 * 创建保存原发器对象状态的备忘录对象
	 * @return 创建好的备忘录对象
	 */
	public FlowAMockMemento createMemento() {
		return new MementoImpl(this.tempResult, this.tempState);
	}
	
	/**
	 * 重新设置原发器对象的状态,让其回到备忘录对象记录的状态
	 * @param memento 记录有原发器状态的备忘录对象
	 */
	public void setMemento(FlowAMockMemento memento) {
		MementoImpl mementoImpl = (MementoImpl)memento;
		this.tempResult = mementoImpl.getTempResult();
		this.tempState = mementoImpl.getTempState();
	}
}

\pattern\FlowAMementoCareTaker.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 负责保存模拟运行流程A的对象的备忘录对象 
 */
public class FlowAMementoCareTaker {
    /**
     * 记录被保存的备忘录对象
     */
	private FlowAMockMemento memento = null;
	
	/**
	 * 保存备忘录对象
	 * @param memento 被保存的备忘录对象
	 */
	public void saveMemento(FlowAMockMemento memento) {
		this.memento = memento;
	}
	
	/**
	 * 获取被保存的备忘录对象
	 * @return 被保存的备忘录对象
	 */
	public FlowAMockMemento retriveMemento() {
		return this.memento;
	}
}

\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package user;

import pattern.FlowAMementoCareTaker;
import pattern.FlowAMock;
import pattern.FlowAMockMemento;

public class Client {
	public static void main(String[] args) {
        // 创建模拟运行流程的对象
		FlowAMock mock = new FlowAMock("TestFlow");
		
		// 运行流程的第一个阶段
		mock.runPhaseOne();
		
		// 创建一个管理者
		FlowAMementoCareTaker careTaker = 
			new FlowAMementoCareTaker();
		
		// 创建此时对象的备忘录对象,并保存到管理者对象那里,后面要用
		FlowAMockMemento memento = mock.createMemento();
		careTaker.saveMemento(memento);
		
		// 按照方案一来运行流程的后半部分
		mock.schema1();
		
		// 从管理者获取备忘录对象,然后设置回去
		// 让模拟运行流程的对象自己恢复自己的内部状态
		mock.setMemento(careTaker.retriveMemento());
		// mock.setMemento(memento);
		
		// 按照方案二来运行流程的后半部分
		mock.schema2();
	}
}

@@@模式的实现:
引入一个存储状态的备忘录对象,让它作为原发器的私有内部类。
引入一个备忘录对象的窄接口,和外部通信。

@@@模式的优点:
(1)更好的封装性;
(2)简化了原发器;

@@@模式的缺点:
可能会导致高开销;

@@@模式的本质:
保存和恢复内部状态。

@@@模式体现的设计原则:
NA

抱歉!评论已关闭.