一、备忘录模式的定义
Without violating encapsulation,capture and externalize an object's internal state so that the object can be restored to this state later.(在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原来保存的状态)
二、备忘录模式的应用
-
备忘录模式的优点
有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取,这时,使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。
本模式简化了发起人。发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。
当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
-
备忘录模式的缺点
、如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
2、当负责人角色将一个备忘录 存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。
3、当发起人角色的状态改变的时候,有可能这个协议无效。如果状态改变的成功率不高的话,不如采取“假如”协议模式。
-
备忘录模式使用场景。
需要保存和恢复数据的相关状态场景。提供一个可回滚(rollback)的操作;比如Word中的CTRL+Z组合键,IE浏览器中的后退按钮,文件管理器上的backspace键等。需要监控的副本场景中。数据库连接的事务管理就是用的备忘录模式,想想看,如果你要实现一个JDBC驱动,你怎么来实现事务?还不是用备忘录模式嘛!
三、备忘录模式的实现
/**
* 【简单标准的备忘录模式】的发起者
*
*/
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 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;
}
}
package com.yeepay.sxf.template19;
/**
* 备忘录模式测试
* @author sxf
*
*/
public class ClientTest {
public static void main(String[] args) {
test();
}
/**
* 简单的备忘录模式
*/
public static void test(){
//定义发起人
Originator originator=new Originator();
//初始化状态
originator.setState("初始化");
//定义备忘录管理员
Caretaker caretaker=new Caretaker();
//给备忘录管理员放入备忘录
caretaker.setMemento(originator.createMemento());
//模拟一系列操作修改发起者的状态
originator.setState("失败了");
//经过一系列操作,回复备忘录
originator.restoreMemento(caretaker.getMemento());
System.out.println("ClientTest.test01()"+originator.getState());
}
}
四、备忘录模式源码中的应用
protected void onSaveInstanceState(Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
//View视图树的状态保存 就一行
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
PhoneWindow:
@Override
public Bundle saveHierarchyState() {
//省略其他无关代码
SparseArray<Parcelable> states = new SparseArray<Parcelable>();//创建数据对象
mContentParent.saveHierarchyState(states);//给数据对象赋值
outState.putSparseParcelableArray(VIEWS_TAG, states);//存入保存结构中
....
}
Activity:作为备忘录管理者,一个单纯的管理者,控制原发器的的保存和恢复,关于数据的保存使用其他组件Bundle类的机制实现。
Bundle:逻辑上作为标识类(窄接口),实际上使用具有序列化保存数据能力的Bundle实现。
View:作为原发器,它负责向管理者提供封装好的内部数据封装