备忘录模式

备忘录模式

在对一个对象进行操作时,希望这个操作时可回退的。那么就要保存每一步操作时前一步对象的状态。

这个时候可以用备忘录模式。

组成部分

  • 需要记录状态的类
  • 保存对象当前状态和历史状态的类--备忘录类
  • 管理备忘录类的类----提供对备忘录中的对象进行增删改查的方法

1.需要记录状态的类

 1 @Data
 2 public class BasePo {
 3     private String id;
 4 }
 5 
 6 @Data
 7 @EqualsAndHashCode(callSuper=false)
 8 public class Student extends BasePo{
 9     private String name;
10     private int age;
11     private String grade;
12 }

2.备忘录类--(保存历史状态时为了减少存储所需空间将对象序列化成了json)

 1 public class Memento<T extends BasePo> {
 2     private T currentState;
 3 
 4     private LinkedList<String> stateJson;
 5 
 6     public T getCurrentState() {
 7         return currentState;
 8     }
 9 
10     @SuppressWarnings("unchecked")
11     public void setCurrentState(Object currentState) {
12         this.currentState = (T) currentState;
13     }
14 
15     public LinkedList<String> getStateJson() {
16         return stateJson;
17     }
18 
19     public void setStateJson(LinkedList<String> stateJson) {
20         this.stateJson = stateJson;
21     }
22 
23     @Override
24     public String toString(){
25         Field[] fields = currentState.getClass().getDeclaredFields();
26         StringBuilder builder = new StringBuilder();
27         for (Field field : fields) {
28             field.setAccessible(true);
29             String firstLetter = field.getName().substring(0,1).toUpperCase();
30             String getMethodName = "get"+firstLetter+field.getName().substring(1);
31             try {
32                 Method getMethod = currentState.getClass().getMethod(getMethodName, new Class[] {}); 
33                 builder.append(" 字段[");
34                 builder.append(field.getName());
35                 builder.append("] has value   ");
36                 builder.append(getMethod.invoke(currentState, new Object[] {})); 
37             } catch (Exception e) {
38                  
39             }
40             
41         }
42         return builder.toString();
43     }
44 }

备忘录类的管理类

public class MementoManage<T extends BasePo> {
    private HashMap<String, Memento<T>> map = new HashMap<String, Memento<T>>();
    
    public Class<?> getTClass(T t) {
        return t.getClass();
    }
    
    public void add(T entity) throws IllegalAccessException, InvocationTargetException, InstantiationException{
        if (map.containsKey(entity.getId())) {
            update(entity);
        }else {
            Memento<T> memento = new Memento<T>();
            Object t = this.getTClass(entity).newInstance();
            BeanUtils.copyProperties(t, entity);
            memento.setCurrentState(t);
            memento.setStateJson(new LinkedList<String>());
            map.put(entity.getId(), memento);
            System.out.println(memento.toString());
        }
    }
    
    public void update(T entity) throws IllegalAccessException, InvocationTargetException, InstantiationException{
        Memento<T> memento = map.get(entity.getId());
        String json = new Gson().toJson(memento.getCurrentState());
        memento.getStateJson().addLast(json);
        Object t = this.getTClass(entity).newInstance();
        BeanUtils.copyProperties(t, entity);
        memento.setCurrentState(t);
        System.out.println(memento.toString());
    }
    
    public void cancel(T entity){
        Memento<T> memento = map.get(entity.getId());
        if (memento.getStateJson().size()==0) {
            System.out.println("沒有可回退的操作");
            System.out.println(memento.toString());
        }else {
            String json = memento.getStateJson().getLast().toString();
            memento.setCurrentState(new Gson().fromJson(json, Student.class));
            memento.getStateJson().removeLast();
            System.out.println(memento.toString());
        }
    }
    
    public void delete(T entity){
        if (map.containsKey(entity.getId())) {
            map.remove(entity.getId());
        }
    }
}

测试类

 1 public static void main(String[] args) throws IllegalAccessException,
 2             InvocationTargetException, InstantiationException {
 3         Student student = new Student();
 4         student.setId(UUID.randomUUID().toString());
 5         student.setAge(19);
 6         student.setName("小红");
 7         student.setGrade("大一");
 8         MementoManage<Student> manage = new MementoManage<Student>();
 9 
10         manage.add(student);
11 
12         student.setAge(22);
13         manage.update(student);
14 
15         manage.cancel(student);
16 
17         student.setGrade("初三");
18         manage.update(student);
19 
20         manage.cancel(student);
21         manage.delete(student);
22         
23     }

测试结果

字段[name] has value   小红 字段[age] has value   19 字段[grade] has value   大一
字段[name] has value   小红 字段[age] has value   22 字段[grade] has value   大一
字段[name] has value   小红 字段[age] has value   19 字段[grade] has value   大一
字段[name] has value   小红 字段[age] has value   22 字段[grade] has value   初三
字段[name] has value   小红 字段[age] has value   19 字段[grade] has value   大一

 

posted on 2018-07-24 16:37  xushy  阅读(158)  评论(0编辑  收藏  举报

导航