一天一种设计模式之二-----备忘录模式

一.备忘录模式

  1. 备忘录模式属于三种设计模式中的行为型模式(另外两种是建立型模式和结构型模式)。java

  2. 定义:在不破坏封闭性的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态。这样之后就能够将改变了的对象恢复到原先保存的状态。设计模式

  3. 之因此须要存储改变前的对象,是由于java对象的传递是引用传递。A a1=a,a里面的东西变就等同于a1里面的东西变。
    架构

  4. 备忘录模式的结构:ide

    1. 发起人:负责记录当前时刻的内部状态,负责定义那些属于备忘范围的状态,负责建立和恢复备忘录数据。测试

    2. 备忘录:负责存储发起人对象的内部状态,在须要的时候提供发起人须要的内部状态。this

    3. 管理角色:对备忘录进行管理,保存和提供备忘录。spa

  5. 优势:设计

    1. 当发起人角色中的状态改变时,有可能这是个错误的改变,咱们使用备忘录模式就能够还原。rest

    2. 备份的状态是保存在发起人角色以外的,这样,发起人角色就不须要对哥哥备份状态进行管理。代码规范

    3. 若是有须要提供回滚操做的需求,使用备忘录模式很是合适

  6. 缺点:

    1. 在实际应用中,备忘录模式多事多状态和多备份的,发起人角色的状态须要存储到备忘录对象中,对字段的小号是比较严重的。

  7. 从设计模式角度讲:我的感受他对六大设计模式原则的体现不是很大,只能说知足单一职责原则把,好比一个类的实例若是想要从不能备忘改成须要备忘,经过该模式,咱们仍是要为该类增长一个保存和恢复的方法,违背了开闭原则,client端调用的时候须要知道。为何不直接定义一个容器,拷贝一个该对象,须要回复的时候再赋值过去呢(这样貌似又不三不四了,由于体现不出来备忘是某个对象的能力,略纠结啊)。(欢迎大神透彻分析下)

二.测试代码


  1. 简单版测试用例:

public class BeiwangluTest {
    public static void main(String[] args) {
        Originator originator=new Originator();
        originator.setState("状态1");
        Caretaker caretaker=new Caretaker();
        caretaker.setMemento(originator.createMemento());
        originator.setState("状态2");
        originator.restorMemento(caretaker.getMemento());
        System.out.println(originator.getState());;//这是以前的状态
        originator.createMemento();//这是以前的memento
    }
}
/**
 * 发起ren 
 * @author 58
 *
 */
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 restorMemento(Memento memento){
        this.setState(memento.getState());
    }
    
}
/**
 * 备忘录
 * @author 58
 *
 */
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;
    }
}

/**
 * 管理角色
 * @author 58
 *
 */
class Caretaker{
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }
    
    public void setMemento(Memento memento) {
        this.memento = memento;
    }
    
    
}

    上述代码只作到恢复了一个状态,通常状况下咱们须要恢复的是一个复杂的对象。

    最经常使用的方法是在memento中增长一个map容器来存储全部的状态,在caretaker类中一样适用一个map容器存储全部备份。下面代码以下(应该也能够经过深拷贝实现,经过beanutils来实现会更更简单,有时间的话试试)

        (话外代码规范:写代码时名字要起好,在方法中list list=xxx这种就很差,应该表示清楚list是干吗的,否则看起来很费劲。简单命名应该只出如今循环遍历中,trycatch等代码常常会给咱们生成一个//TODO注释,这个注释不要留,会让有代码洁癖的人反感,能够从eclipese设置里去掉,要是不知道为何,本身去百度//TODO,//XXX,//FIXME 这些注释各自都是干吗用的,严格要求从我作起)

public class BeiwangluTest {
    public static void main(String[] args) {
        Originator ori=new Originator();
        Caretaker caretaker=new Caretaker();
        ori.setState1("中国");
        ori.setState2("强盛");
        ori.setState3("繁荣");
        System.out.println("状态1"+ori);
        
        caretaker.setMemento("001",ori.createMemento());
        ori.setState1("软件");
        ori.setState2("架构");
        ori.setState3("优秀");
        System.out.println("状态2"+ori);
        
        ori.restorMemento(caretaker.getMemento("001"));
        
        System.out.println("回复后的状态"+ori);
    }
}

/**
 * 发起人
 * 
 * @author 58
 *
 */
class Originator {
    private String state1 = "";
    private String state2 = "";
    private String state3 = "";

    public Memento createMemento() {
        return new Memento(BeanUtils.backupProp(this));
    }

    public void restorMemento(Memento memento) {
        BeanUtils.restoreProp(this, memento.getStateMap());
    }

    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;
    }

    @Override
    public String toString() {
        return "Originator [state1=" + state1 + ", state2=" + state2
                + ", state3=" + state3 + "]";
    }

    
}

/**
 * 备忘录
 * 
 * @author 58
 *
 */
class Memento {
    private Map<String, Object> stateMap;

    public Memento(Map<String, Object> map) {
        this.stateMap = map;
    }

    public Map<String, Object> getStateMap() {
        return stateMap;
    }

    public void setStateMap(Map<String, Object> stateMap) {
        this.stateMap = stateMap;
    }

}

/**
 * 管理角色
 * 
 * @author 58
 *
 */
class Caretaker {
    private Map<String, Memento> meMap = new HashMap<String, Memento>();

    public Memento getMemento(String index) {
        return meMap.get(index);
    }

    public void setMemento(String index, Memento memento) {
        this.meMap.put(index, memento);
    }

    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }

}

class BeanUtils {
    public static Map<String, Object> backupProp(Object bean) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
            PropertyDescriptor[] descriptors = beanInfo
                    .getPropertyDescriptors();
            for (PropertyDescriptor descriptor : descriptors) {
                String fieldName = descriptor.getName();
                Method getter = descriptor.getReadMethod();
                // TODO null和new Object[]{}是不同的,null通常是执行抽象方法。
                Object fieldValue = getter.invoke(bean, new Object[]{});
                if (!fieldName.equalsIgnoreCase("class")) {
                    result.put(fieldName, fieldValue);
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void restoreProp(Object bean, Map<String, Object> propMap) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
            PropertyDescriptor[] descriptors = beanInfo
                    .getPropertyDescriptors();
            for (PropertyDescriptor descriptor : descriptors) {
                String fieldName = descriptor.getName();
                if (propMap.containsKey(fieldName)) {
                    Method setterMethod = descriptor.getWriteMethod();
                    setterMethod.invoke(bean,
                            new Object[] { propMap.get(fieldName) });
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
相关文章
相关标签/搜索