原文:http://blog.csdn.net/hackerain/article/details/7563246
定义:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态。
备忘录模式主要是对某个对象的状态的备份,备份的主要是对象当前的属性值,即成员变量的值,成员变量可以有多个,而且可以备份同一个对象的多种不同状态,即同一个对象可以同时有多个备份,先来看最简单的情况,即一个对象只有一个成员变量:
其通用类图为:
源代码如下:
- /*
- * 单属性的备忘录模式,本类即是需要被备份的类
- */
- public class Originator {
- private String state;
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- }
- public void changeState(){
- this.state="heart hurt...";
- }
- public Memento createMemento(){
- return new Memento(this.state);
- }
- public void restoreMemento(Memento memento){
- this.setState(memento.getState());
- }
- }
- /*
- * 备忘录类
- */
- public class Memento {
- private String state;
- public Memento(String state) {
- this.state = state;
- }
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- }
- }
- /*
- * 备忘录管理类
- */
- public class Caretaker {
- private Memento memento;
- public Memento getMemento() {
- return memento;
- }
- public void setMemento(Memento memento) {
- this.memento = memento;
- }
- }
- public class Client {
- public static void main(String[] args) {
- Originator originator=new Originator();
- Caretaker caretaker=new Caretaker();
- originator.setState("happy...");
- System.out.println(originator.getState());
- //保存当前的状态
- caretaker.setMemento(originator.createMemento());
- //状态改变
- originator.changeState();
- System.out.println(originator.getState());
- //恢复状态
- originator.restoreMemento(caretaker.getMemento());
- System.out.println(originator.getState());
- }
- }
要是遇到多属性怎么办?要是一个对象不仅仅只需要备份一次,而需要备份很多次,又该如何呢?看下面改进源码:
- /*
- * 多属性的备忘录模式
- */
- public class Originator {
- private String state1;
- private String state2;
- private String state3;
- public String getState1() {
- return state1;
- }
- public void setState1(String state1) {
- this.state1 = state1;
- }
- public String getState2() {
- return state2;
- }
- public void setState2(String state2) {
- this.state2 = state2;
- }
- public String getState3() {
- return state3;
- }
- public void setState3(String state3) {
- this.state3 = state3;
- }
- //将本对象的各个属性以HashMap类型保存到Memento对象中
- public Memento createMemento(){
- return new Memento(BeanUtils.beanToHash(this));
- }
- //从Memento对象中取出保存的对象的属性状态,并赋值给本对象的各个属性
- public void restoreMemento(Memento memento){
- BeanUtils.hashToBean(this, memento.getStateMap());
- }
- public String toString(){
- return this.state1+" "+this.state2+" "+this.state3;
- }
- }
- //Memento的成员变量为一个HashMap类型的,是为了保存源目标对象的各个属性的名和值
- public class Memento {
- private HashMap<String,Object> stateMap;
- public Memento(HashMap<String, Object> stateMap) {
- this.stateMap = stateMap;
- }
- public HashMap<String, Object> getStateMap() {
- return stateMap;
- }
- public void setStateMap(HashMap<String, Object> stateMap) {
- this.stateMap = stateMap;
- }
- }
- /**
- * 多备份备份,即可以备份一个对象的多种状态,
- * 注意这种多备份,不要用于备份特别频繁的地方,容易出现内存溢出,
- * 或者增加Map的上限,防止出现内存的泄漏。
- */
- public class Caretaker {
- private HashMap<String,Memento> mementos=new HashMap<String,Memento>();
- public Memento getMemento(String key) {
- return mementos.get(key);
- }
- public void setMemento(String key, Memento memento) {
- this.mementos.put(key, memento);
- }
- }
- /*
- * 使用此类是为了操作方便
- */
- public class BeanUtils {
- /*
- * 把bean的所有属性及数值放到HashMap中
- */
- public static HashMap<String,Object> beanToHash(Object bean){
- HashMap<String,Object> result=new HashMap<String,Object>();
- try{
- BeanInfo beanInfo=Introspector.getBeanInfo(bean.getClass());//获得bean描述
- PropertyDescriptor[] descriptors=beanInfo.getPropertyDescriptors();//获得属性描述
- //遍历所有属性
- 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 hashToBean(Object bean, HashMap<String,Object> result){
- try{
- BeanInfo beanInfo=Introspector.getBeanInfo(bean.getClass());//获得bean描述
- PropertyDescriptor[] descriptors=beanInfo.getPropertyDescriptors();//获得属性描述
- //遍历所有属性
- for(PropertyDescriptor des : descriptors){
- String fieldName=des.getName();//属性名
- if(result.containsKey(fieldName)){
- Method setter=des.getWriteMethod();//写属性的方法
- setter.invoke(bean, new Object[]{result.get(fieldName)});//将值写入到属性中
- }
- }
- }catch(Exception e){
- }
- }
- }
- public class Client {
- public static void main(String[] args) {
- Originator originator=new Originator();
- Caretaker caretaker=new Caretaker();
- originator.setState1("brave");
- originator.setState2("responsibility");
- originator.setState3("clever");
- System.out.println("001: "+originator.toString());
- caretaker.setMemento("001",originator.createMemento());//创建第一个备份
- originator.setState1("weak");
- originator.setState2("lazy");
- originator.setState3("temper");
- System.out.println("002: "+originator.toString());
- caretaker.setMemento("002",originator.createMemento());//创建第二个备份
- originator.setState1("self-reflection");
- originator.setState2("get up early");
- originator.setState3("go to libyary everyday");
- System.out.println("003: "+originator.toString());
- caretaker.setMemento("003",originator.createMemento());//创建第三个备份
- originator.restoreMemento(caretaker.getMemento("001"));//恢复
- System.out.println("now: "+originator.toString());
- }
- }
另外,备份还可以有另外一种实现方式,备份嘛,自然会联想到复制,也就联想到原型模型了,可以使用克隆的方法来实现备忘录,如下源码:
- /*
- * 通过克隆对象的方式实现备忘录
- */
- public class Originator implements Cloneable{
- private String state;
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- }
- public void changeState(){
- this.state="heart hurt...";
- }
- public Originator createMemento(){
- return this.clone();
- }
- public void restoreMemento(Originator originator){
- this.setState(originator.getState());
- }
- @Override
- protected Originator clone(){
- try{
- return (Originator)super.clone();
- }catch(CloneNotSupportedException e){
- e.printStackTrace();
- }
- return null;
- }
- }
- public class Caretaker {
- private Originator originator;
- public Originator getMemento() {
- return originator;
- }
- public void setMemento(Originator originator) {
- this.originator = originator;
- }
- }
- public interface IMemento {
- }
- /*
- * 使用内部类,增强安全性
- */
- public class Originator {
- private String state;
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- }
- public void changeState(){
- this.state="heart hurt...";
- }
- public Memento createMemento(){
- return new Memento(this.state);
- }
- public void restoreMemento(IMemento memento){
- this.setState(((Memento)memento).getState());
- }
- //把备忘录类写成内部类,这样只有发起人才能访问备忘录,其他对象都不可以访问,这就增加了备忘录的安全性
- //实现了一个空的接口,以便于在外边和其他类产生关联关系。
- private class Memento implements IMemento {
- private String state;
- private Memento(String state) {
- this.state = state;
- }
- private String getState() {
- return state;
- }
- }
- }
- //在原发起类的外部使用备忘录类的空接口建立和其他对象的关联
- public class Caretaker {
- private IMemento memento;
- public IMemento getMemento() {
- return memento;
- }
- public void setMemento(IMemento memento) {
- this.memento = memento;
- }
- }
备忘录模式的使用场景:
1、需要保存和恢复数据的相关状态场景
2、数据库连接的事务管理就是用的备忘录模式