备忘录模式

针对问题

现有一个可变的类,其内部状态不断变化,我们想要捕捉其中的变化,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。这种情况下可以用备忘录模式。

如何实现

创建两个类并在原先的可变类中添加一些方法即可。首先在状态的产生类定义两个方法,可以产生状态和复原状态;然后创建一个备忘录类作为状态存储的单元结构;之后再创建一个类用来管理所有已有的状态,即保存于很多个备忘录类的实例。客户不与备忘录类耦合,与备忘录管理类耦合。

优点

1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

例子

1、后悔药。
2、打游戏时的存档。
3、Windows 里的 ctri + z。
4、IE 中的后退。
5、数据库的事务管理。

类图

在这里插入图片描述

实例展示

这里我们给出一个原子轨道系统中电子跃迁的例子,这里的状态就是电子的分布情况。首先我们要能够保存和复原状态,即在原始类里面添加方法,如下:

package circularOrbit;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import centralObject.Nucleus;
import memento.Memento;
import physicalObject.Electron;
import track.Track;
/**
 * A Person
 * immutable.
 * 
 */
public class AtomStructure extends ConcreteCircularOrbit<Nucleus, Electron> {
	private final static String type = "AtomStructure";
	private String state = "";
	private final Map<Integer, Integer> eletronnumbrestate = new HashMap<Integer, Integer>();
	// Abstraction function:
	// type represent the type of ConcreteCircularOrbit.
	// state represent electron distribution information in orbit.
	// eletronnumbrestate represent electron distribution in orbit.
	// Representation invariant:
	// The state must be in the format of "1/2;2/4;3/15".
	// The eletronnumbrestate must match the state.
	// Safety from rep exposure:
	// No observer.


	/*
	 *......
	 *中间删去了其他方法
	 *......
	 */

	/**
     * Reset the distribution of electrons according to the given state.
     * @param the target state.
     */
	public void setState(String state) {
		this.state = state;
		Nucleus cenNucleus = getcentralObject();
		this.empty();
		String[] infos = state.split(";");
		for (int i = 0; i < infos.length; i++) {
			String string = infos[i];
			int index2 = string.indexOf('/');
			String first = string.substring(0, index2);
			int firstnum = Integer.valueOf(first);
			String second = string.substring(index2 + 1);
			int secondnum = Integer.valueOf(second);
			eletronnumbrestate.put(firstnum, secondnum);
		}
		this.addCentralObject(cenNucleus);
		for (int i = 1; i <= eletronnumbrestate.size(); i++) {
			int electronnum = eletronnumbrestate.get(i);
			for (int j = 1; j <= electronnum; j++) {
				Electron newelec = new Electron(i + "-" + j);
				this.addAPhysicalObject(i, newelec);
			}
		}
	}
	/**
     * Gets the state of the current electron distribution.
     * 
     * 
     * 
     * @return the current state.
     */
	public String getState() {
		String currentstate = "";
		for (int i = 0; i < getTracks().size(); i++) {
			Track tempTrack = getTracks().get(i);
			int size = getPhysicalObjectOfTrack(tempTrack).size();
			currentstate = currentstate + tempTrack.getRadius() + '/' + size + ";";
			eletronnumbrestate.put(tempTrack.getRadius(), size);
		}
		if (currentstate.length() == 0) {
			return "";
		}
		currentstate = currentstate.substring(0, currentstate.length()-1);
		state = currentstate;
		return state;
	}
	/**
     * Save the state to a new memoto.
     * 
     * 
     * 
     * @return Memoto generated from the current state.
     */
	public Memento saveStateToMemento() {
		return new Memento(getState());
	}
	/**
     * Reset the distribution of electrons according to the given memento.
     * 
     * 
     * @param Memoto for storage state.
     */
	public void getStateFromMemento(Memento Memento) {
		state = Memento.getState();
		setState(state);
	}
}

可以发现我们这里实际上给出了四个方法,其中前面两个是为了内部获取和复原状态,后面两个才是实际上和备忘录交互用的。
之后我们需要创建备忘录类,作为存储状态的单元,如下:

package memento;
/**
 * A memento.
 * immutable.
 * 
 */
public class Memento {
	private final String state;
	// Abstraction function:
	// The state represent the state stored.
	// Representation invariant:
	// Nothing.
	// Safety from rep exposure:
	// state is immutable.
	/**
	 * Create a new memento.
	 * 
	 */
	public Memento(String state) {
		this.state = state;
	}
	/**
	 * Get the state.
	 * 
	 * @return the state.
	 */
	public String getState() {
		return state;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((state == null) ? 0 : state.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Memento other = (Memento) obj;
		if (state == null) {
			if (other.state != null)
				return false;
		} else if (!state.equals(other.state))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Memento [state=" + state + "]";
	}
}

最后我们创建一个备忘录的管理类用于和客户端进行交互即可,如下:

package memento;

import java.util.ArrayList;
import java.util.List;
/**
 * A CareTaker.
 * The caretaker is responsible for the storage of all memotos.
 * mutable.
 * 
 */
public class CareTaker {
	private final List<Memento> mementoList = new ArrayList<Memento>();
	// Abstraction function:
	// mmementoList represent all mementos.
	// Representation invariant:
	// Nothing.
	// Safety from rep exposure:
	// mementoList is private and final.
	/**
     * Add a memento.
     * 
     * 
     * @param the memento need to be added.
     */
	public void add(Memento state) {
		mementoList.add(state);
	}
	/**
     * Get a memento.
     * 
     * 
     * @param the index of the memento in the mmementoList.
     * @return the memento.
     */
	public Memento get(int index) {
		if (index >= mementoList.size()) {
			return null;
		}
		return mementoList.get(index);
	}
	/**
     * Show all state information through a string.
     * 
     * 
     * 
     */
	public void showAllStates() {
		System.out.println("All States:");
		for (int i = 0; i < mementoList.size(); i++) {
			Memento tempMemento = mementoList.get(i);
			System.out.println("\tState" + (i+1) + ":" + tempMemento.getState());
		}
	}
	@Override
	public String toString() {
		// TODO 自动生成的方法存根
		return mementoList.toString();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值