3) 備忘錄管理者(Caretaker)角色:負責保存好備忘錄。不能對備忘錄的內容進行操作或檢查。
public class Originator {
private String state="";
public void changeState(){
this.state="maybe not so good";
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento createMemote(){
return new Memento(this.state);
}
public void restoreMomoto(Memento _memoto){
this.setState(_memoto.getState());
}
}
public class Memento {
private String state="";
public Memento(String _state) {
this.state=_state;
}
public String getState() {
return this.state;
}
}
public class Caretaker {
private Memento memoto;
public Memento getMemoto(){
return memoto;
}
public void setMemoto(Memento memoto){
this.memoto=memoto;
}
}
public class Client {
public static void main(String[] args) {
Originator orihinator=new Originator(); //發起人
Caretaker caretaker=new Caretaker(); //備忘錄管理者,不能改變內容
orihinator.setState("It's so good"); //設置狀態
caretaker.setMemoto(orihinator.createMemote()); //創建備份點
orihinator.changeState(); //改變狀態
orihinator.restoreMomoto(caretaker.getMemoto()); //恢復至備份點
}
}
/*
* 這樣看來,Memoto備忘錄就是一個JavaBean,存儲數據。
* 爲什麼還需要Caretaker? 爲了不違背迪米特原則,只和朋友類交流,備份類不是朋友,系統需求只是在某個點創建備份
* 所以備忘錄管理類就出來了,看起來又是一個JavaBean,在備忘錄之上又包裝了一層,麻煩,但是這樣結構清晰了許多
* 發起人不需要和備份類交流
*
* 例子 : 網站 -> 瀏覽器 -> cookie -> 網站...
* 用戶發送一個請求給服務器,服務器會創建一個相對應的session對象,發送數據至瀏覽器並設置cookie,在一段時間裏
* 用戶可以訪問服務器,服務器可以根據sessionID來判斷是哪個session對象
*/
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) {
//異常處理
}
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) {
//異常處理
System.out.println("shit");
e.printStackTrace();
}
}
}
public class Caretaker {
//容納備忘錄的容器
private HashMap<String,Memento> memMap = new HashMap<String,Memento>();
public Memento getMemento(String idx) {
return memMap.get(idx);
}
public void setMemento(String idx,Memento memento) {
this.memMap.put(idx, memento);
}
}
public class Originator {
private String state1=""; //狀態1
private String state2=""; //狀態2
private String state3=""; //狀態3
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的構造方法注入startMap中
* @return
*/
public Memento createMemote(){
return new Memento(BeanUtils.backupProp(this));
}
/**
* 因爲權限的關係,外部不可能傳進來一個Memento對象,這裏就將就的使用了一個HashMap集合
* 通過反射,將該實例的所有屬性值替換成hashMap中的值
* @param map
*/
public void restoreMomoto(HashMap<String,Object> map){
BeanUtils.restoreProp(this, map);
}
/**
* 內置類,別人不可能訪問
* 實現一個空接口是爲了與外部關聯,在實際的開發中一個業務接口,一個空接口用於其它子模塊,通過反射就可以爲所欲爲了
* @author suibian
*/
private class Memento implements IMemento{
private HashMap<String,Object> startMap;
public Memento(HashMap<String,Object> _startMap) {
this.startMap=_startMap;
}
public HashMap<String, Object> getStartMap() {
return startMap;
}
public void setStartMap(HashMap<String, Object> startMap) {
this.startMap = startMap;
}
}
/*測試使用
*/
@Override
public String toString() {
return "state1="+state1+"\t state2="+state2+"\t state3="+state3;
}
}
public class Caretaker {
private HashMap<String,IMemento> map=new HashMap<String,IMemento>();
public IMemento getMemoto(String idx){
return map.get(idx);
}
/**
* 多個備份
* @param idx 時間銼
* @param memoto 備份接口
*/
public void setMemoto(String idx,IMemento memoto){
this.map.put(idx, memoto);
}
}
public class Client {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
Originator ori1 = new Originator();
Caretaker caretaker = new Caretaker();
ori1.setState1("備份1狀態1");
ori1.setState2("備份1狀態2");
ori1.setState3("備份1狀態3");
caretaker.setMemoto("第一個", ori1.createMemote());
Originator ori2 = new Originator();
ori2.setState1("備份2狀態1");
ori2.setState2("備份2狀態2");
ori2.setState3("備份2狀態3");
caretaker.setMemoto("第二個", ori2.createMemote());
System.out.println(ori1.toString());
System.out.println(ori2.toString());
System.out.println("----------------------備份完畢----------------------------");
ori1.setState1("備份1狀態1改變了");
System.out.println("改變後的:"+ori1.toString());
System.out.println("-----------------------開始恢復-----------------------------");
IMemento memento = caretaker.getMemoto("第一個"); //從備份管理獲取備份實例
//得到是Memento中的屬性startMap再轉化成能注參的map對象
HashMap<String,Object> data=(HashMap<String, Object>) BeanUtils.backupProp(memento).get("startMap");
for(Entry<String, Object> e:data.entrySet()){
System.out.println("這是存起來的備份數據:"+e.getKey()+"\t"+e.getValue());
}
//將備份實例中的數據data通過反射注入到ori1中去
ori1.restoreMomoto(data);
System.out.println("------------------恢復完後的數據-------------------------");
System.out.println(ori1.toString());
System.out.println(ori2.toString());
}
}
/*錯誤地方
*通過 BeanUtils.backupProp(memento)獲取的是對象Memento類的所有屬性值
*而Originator恢復需要的是一個hashMap通過反射注參,一個屬性名對應一個值,而上面獲取的hashMap是一個屬性名,一個hashMap對象
*因爲權限只能由Originator來恢復,所以修改了restoreMomoto()方法,不傳Memento,而傳一個HashMap對象
*/
不得不說,這個真麻煩。
我是菜鳥,我在路上。