定义:
- 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
备忘录模式的通用类图:
/*
* 定义备忘录角色
* */
public class Memento {
// 发起人的内部角色
private String state = "";
public Memento(String state) {
// TODO Auto-generated constructor stub
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 Originator {
// 内部状态
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());
}
}
public class Client {
public static void main(String[] args) {
// 定义发起人
Originator originator = new Originator();
// 创建备忘录管理者
Caretaker caretaker = new Caretaker();
// 创建备忘录
caretaker.setMemento(originator.createMemento());
// 恢复备忘录
originator.restoreMemento(caretaker.getMemento());
}
}
使用场景
- 需要保存和恢复数据的相关状态场景。
- 提供一个可回滚(rollback)的操作
- 需要监控的副本场景中。备份一个主线程中的对象,然后由分析程序来分析
- 数据库连接的事务管理就是用的备忘录模式
注意事项:
- 备忘录的生命周期:创建出来后,要在"最近"的代码中使用,要主动管理它的生命周期,建立就要使用,不是用就要立刻删除,等待垃圾回收器对它的回收处理。
- 备忘录的性能:不要再频繁建立备份的场景中使用备忘录模式(for循环),一是控制不了备忘录建立的对象数量,二是大对象的建立是要消耗资源的,影响性能。
备忘录模式拓展:
public class Caretaker {
private Originator originator;
public Originator getOriginator() {
return originator;
}
public void setOriginator(Originator originator) {
this.originator = originator;
}
}
public class Originator implements Cloneable {
// 将发起者和备忘录角色进行合并
private String state = "";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
// 创建备忘录角色
public Originator createMemento() {
return this.clone();
}
// 恢复备忘录角色
public void restoreMemento(Originator _originator) {
this.setState(_originator.getState());
}
@Override
protected Originator clone() {
// TODO Auto-generated method stub
try {
return (Originator) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
/*
* 去掉管理员角色,精简
* 设计模式定义的诞生比JAVA的出世略早,没有想到
* java在面向对象的设计中,可以实现把一个类封装在另一个类中
* */
public class OriginatorMix implements Cloneable {
private OriginatorMix originatorMix;
private String state = "";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public void setMemento() {
originatorMix = this.clone();
}
public void restoreMemento() {
this.setState(this.originatorMix.getState());
}
@Override
protected OriginatorMix clone() {
// TODO Auto-generated method stub
try {
return (OriginatorMix) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public class Cient {
public static void main(String[] args) {
//使用clone方式一实现
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
caretaker.setOriginator(originator);//备份
originator.restoreMemento(caretaker.getOriginator());//恢复
//使用clone方式二实现
OriginatorMix originatorMix = new OriginatorMix();
System.out.println("init");
originatorMix.setState("初始状态");
System.out.println(originatorMix.getState());
System.out.println("memento");
originatorMix.setMemento();
originatorMix.setState("备份后的状态");
System.out.println(originatorMix.getState());
originatorMix.restoreMemento();
System.out.println("recover memento");
System.out.println(originatorMix.getState());
}
}
发起人角色融合了发起人角色和备忘录角色,具有双重功效。使用clone方式的备忘录,可以使用在比较简单的场景或者比较单一的场景中,尽量不要与其他的对象产生严重的耦合关系。对于深拷贝,考虑对应的语句书写。
/*
* 定义备忘录角色
* */
public class Memento {
// 接受HashMap作为备份状态
private HashMap<String, Object> hashMap;
public HashMap<String, Object> getStateMap() {
return hashMap;
}
public void setHashMap(HashMap<String, Object> hashMap) {
this.hashMap = hashMap;
}
// 接收一个对象,建立一个备份
public Memento(HashMap<String, Object> hashMap) {
// TODO Auto-generated constructor stub
this.hashMap = hashMap;
}
}
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;
}
// 创建一个备忘录
public Memento createMemo() {
return new Memento(BeanUtils.backupProp(this));
}
// 恢复一个备忘录
public void restoreMemento(Memento _memento) {
BeanUtils.restoreProp(this, _memento.getStateMap());
}
// 增加 toString
@Override
public String toString() {
// TODO Auto-generated method stub
return "state1=" + state1 + "state2=" + state2 + "state3=" + state3;
}
}
/*
* 创建备忘录管理者
* */
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
public class BeanUtils {
// 把bean的所有属性及数值放入到Hashmap中
public static HashMap<String, Object> backupProp(Object bean) {
HashMap<String, Object> result = new HashMap<>();
try {
// 获取Bean描述
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
// 获取相关的属性描述
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// 获取属性名的值
String fieldName = propertyDescriptor.getName();
// 读取属性的get方法
Method getter = propertyDescriptor.getReadMethod();
// 读取属性值
Object fieldValue = getter.invoke(bean, new Object[] {});
if (!fieldName.equalsIgnoreCase("class"))
result.put(fieldName, fieldValue);
}
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
// 把HashMap放到bean中
public static void restoreProp(Object bean, HashMap<String, Object> propMap) {
try {
// 获取Bean描述
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
// 获取相关的属性描述
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String fieldName = propertyDescriptor.getName();
// 判断对应的属性是否存在
if (propMap.containsKey(fieldName)) {
// 写属性方法
Method setter = propertyDescriptor.getWriteMethod();
setter.invoke(bean, new Object[] { propMap.get(fieldName) });
}
}
} catch (Exception e) {
// 异常处理
}
}
}
public class Client {
public static void main(String[] args) {
// 定义出发起人
Originator originator = new Originator();
// 定义出备忘录管理员
Caretaker caretaker = new Caretaker();
originator.setState1("1");
originator.setState2("2");
originator.setState3("3");
System.out.println("初始化状态:" + originator.toString());
// 创建备忘录
caretaker.setMemento(originator.createMemo());
originator.setState1("6");
originator.setState2("5");
originator.setState3("4");
System.out.println("更新状态:" + originator.toString());
// 恢复备忘录
originator.restoreMemento(caretaker.getMemento());
System.out.println("恢复后的状态为:" + originator.toString());
}
}
- 多备份备份
/*
* 多备份管理员,通过hashmap作为数据存储的载体
* */
public class Caretaker {
// 容纳备忘录的容器
private HashMap<String, Memento> menMap = new HashMap<>();
public Memento getMemento(String idx) {
return this.menMap.get(idx);
}
// 注意内存溢出问题,该备份一旦产生就放入到内存中,没有销毁的意向,
// 所以在系统设计的时候,要严格限定备忘录的创建。建议增加Map的上限
// 否则很容易产生内存溢出的情况
public void storeMemento(String idx, Memento memento) {
this.menMap.put(idx, memento);
}
}
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
caretaker.storeMemento("1", originator.createMemo());
caretaker.storeMemento("2", originator.createMemo());
// 恢复到指定状态的备忘录
originator.restoreMemento(caretaker.getMemento("2"));
}
}
- 使用内置类实现备忘录
/*
* 全部通过接口进行访问,
* 如果你想访问它的属性肯定是不行,
* 没有绝对的安全,
* 通过reflect反射修改Memento的数据
* */
public class Caretaker {
private IMemento memento;
public IMemento getMemento() {
return memento;
}
public void setMemento(IMemento memento) {
this.memento = memento;
}
}
/*
* 定义空一个备忘录接口
* */
public interface IMemento {
}
public class Originator {
// 内部状态
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(IMemento _memento) {
this.setState(((Memento) _memento).getState());
}
// 使用内部类实现接口
class Memento implements IMemento {
// 发起人的内部角色
private String state = "";
public Memento(String state) {
// TODO Auto-generated constructor stub
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
}