概要:
该文章参考了《设计模式之禅》一书及一些前辈的博客文章
1.该文章阐述了备忘录模式的基础原理及示例代码;
2.该文章适合初学设计模式的技术人员研习;
3.该文章有许多不足之处,请各位大咖指正,喷子绕道;
4.该文章是《JAVA的23种设计模式—备忘录模式(一)》的续写,点此跳转到第一部分
正文:
4.多状态的备忘录模式示例代码实现:
package com.csdn;
/**
* 发起人角色
* @author Administrator
*
*/
public class Originator {
//内部状态
private String state1;
private String state2;
private String state3;
//getter、setter
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 createMemento(){
return new Memento(BeanUtils.backupProp(this));
}
//恢复备份
public void restoreMemento(Memento _memento){
BeanUtils.restoreProp(this,_memento.getStateMap());
}
@Override
public String toString() {
return "Originator [state1=" + state1 + ", state2=" + state2 + ", state3=" + state3 + "]";
}
}
package com.csdn;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* 工具类
* @author Administrator
*
*/
public class BeanUtils {
//bean所有属性和数值放入到Hashmap中
public static HashMap<String,Object> backupProp(Object bean){
HashMap<String,Object> result = new HashMap<String,Object>();
try {
//获得bean描述
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
//获得属性描述
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 restoreProp(Object bean,HashMap<String, Object> propMap){
try {
//获得bean描述
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
//获得属性描述
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
//遍历所有属性
for(PropertyDescriptor des:descriptors){
//属性名称
String fieldName = des.getName();
//如果有这个属性
if(propMap.containsKey(fieldName)){
//写属性的方法
Method setter = des.getWriteMethod();
setter.invoke(bean, new Object[]{propMap.get(fieldName)});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.csdn;
import java.util.HashMap;
/**
* 备忘录角色
* @author Administrator
*
*/
public class Memento {
//接受HashMap作为状态
private HashMap<String,Object> stateMap;
//接受一个对象,建立一个备份
public Memento(HashMap<String,Object> map){
this.stateMap = map;
}
public HashMap<String, Object> getStateMap() {
return stateMap;
}
public void setStateMap(HashMap<String, Object> stateMap) {
this.stateMap = stateMap;
}
}
package com.csdn;
/**
* 备忘录管理者角色
* @author Administrator
*
*/
public class Caretaker {
//备忘录对象
private Memento memento;
//getter、setter
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
package com.csdn;
/**
* 场景类
* @author Administrator
*
*/
public class Client {
public static void main(String[] args) {
//定义发起人
Originator originator = new Originator();
//定义备忘录管理员
Caretaker caretaker = new Caretaker();
//初始化
originator.setState1("a");
originator.setState2("b");
originator.setState3("c");
System.out.println("初始化状态:"+originator);
//备份
caretaker.setMemento(originator.createMemento());
//修改状态值
originator.setState1("aa");
originator.setState2("bb");
originator.setState3("cc");
System.out.println("修改后状态:"+originator);
//恢复备份数据
originator.restoreMemento(caretaker.getMemento());
System.out.println("恢复后状态:"+originator);
}
}
输出:
初始化状态:Originator [state1=a, state2=b, state3=c]
修改后状态:Originator [state1=aa, state2=bb, state3=cc]
恢复后状态:Originator [state1=a, state2=b, state3=c]
注:
a:该示例实现了一个JavaBean对象(多个属性)的所有状态的备份及还原
5.多备份的备忘录模式示例代码实现(在第四个示例上进行修改):
package com.csdn;
import java.util.HashMap;
/**
* 备忘录管理者角色
* @author Administrator
*
*/
public class Caretaker {
//容纳备忘录的容器
private HashMap<String, Memento> mementoMap = new HashMap<String, Memento>();
public Memento getMemento(String idx) {
return mementoMap.get(idx);
}
public void setMemento(String idx,Memento memento) {
this.mementoMap.put(idx, memento);
}
}
package com.csdn;
/**
* 场景类
* @author Administrator
*
*/
public class Client {
public static void main(String[] args) {
//定义发起人
Originator originator = new Originator();
//定义备忘录管理员
Caretaker caretaker = new Caretaker();
//初始化并备份
originator.setState1("a");
originator.setState2("b");
originator.setState3("c");
System.out.println("初始化状态:"+originator);
caretaker.setMemento("001",originator.createMemento());
//修改状态值并备份
originator.setState1("aa");
originator.setState2("bb");
originator.setState3("cc");
System.out.println("修改后状态:"+originator);
caretaker.setMemento("002",originator.createMemento());
//恢复初始的备份数据
originator.restoreMemento(caretaker.getMemento("001"));
System.out.println("恢复初始备份数据后的状态:"+originator);
//恢复修改后备份的数据
originator.restoreMemento(caretaker.getMemento("002"));
System.out.println("恢复修改后备份数据后的状态:"+originator);
}
}
输出:
初始化状态:Originator [state1=a, state2=b, state3=c]
修改后状态:Originator [state1=aa, state2=bb, state3=cc]
恢复初始备份数据后的状态:Originator [state1=a, state2=b, state3=c]
恢复修改后备份数据后的状态:Originator [state1=aa, state2=bb, state3=cc]
注:
a:只修改了备忘录管理员类的代码,使得该类中的容器可以存多个备忘录,就可以实现多备份
b:建议增加Map上限,防止内存溢出
6.更好封装备忘录示例代码实现(在第四、五个示例上进行修改):
package com.csdn;
/**
* 备忘录空接口
* @author Administrator
*
*/
public interface IMemento {
}
package com.csdn;
import java.util.HashMap;
/**
* 发起人角色
* @author Administrator
*
*/
public class Originator {
//内部状态
private String state1;
private String state2;
private String state3;
//getter、setter
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 IMemento createMemento(){
return new Memento(BeanUtils.backupProp(this));
}
//恢复备份
public void restoreMemento(IMemento _imemento){
BeanUtils.restoreProp(this,((Memento)_imemento).getStateMap());
}
@Override
public String toString() {
return "Originator [state1=" + state1 + ", state2=" + state2 + ", state3=" + state3 + "]";
}
/**
* 内置类
* @author Administrator
*
*/
private class Memento implements IMemento{
//接受HashMap作为状态
private HashMap<String,Object> stateMap;
//接受一个对象,建立一个备份
private Memento(HashMap<String,Object> map){
this.stateMap = map;
}
private HashMap<String, Object> getStateMap() {
return stateMap;
}
private void setStateMap(HashMap<String, Object> stateMap) {
this.stateMap = stateMap;
}
}
}
package com.csdn;
import java.util.HashMap;
/**
* 备忘录管理者角色
* @author Administrator
*
*/
public class Caretaker {
//容纳备忘录的容器
private HashMap<String, IMemento> mementoMap = new HashMap<String, IMemento>();
public IMemento getMemento(String idx) {
return mementoMap.get(idx);
}
public void setMemento(String idx,IMemento memento) {
this.mementoMap.put(idx, memento);
}
}
注:
a:该示例场景类与输出结果与示例五一致
b:该示例删除了独立的备忘录Memento类,在发起人角色类中增加内置的private Memento备忘录类,并且其实现了IMemento空接口,只有发起者可以访问它,其他类都不可以访问,外界想与备忘录产生关联关系需通过IMemento接口,保证了备忘录的安全
c:双接口设计:考虑对象安全问题,可以提供两个接口。一个是业务正常接口,实现必要的业务逻辑,叫宽接口。另一个接口是空接口,什么方法都没有,目的是提供给子系统外的模块访问,叫窄接口,窄接口相对安全。