美文网首页
备忘录模式

备忘录模式

作者: 忘净空 | 来源:发表于2016-08-18 17:05 被阅读1029次

    模式定义:

    在不破环封装行性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。

    模式场景

    1. 录入大批人员资料的时候。正在录入当前人资料时,发现上一个人录错了,此时需要恢复到上一个人的资料,进行修改。
    1. Word编辑时,忽然断电或电脑死机,再打开时,可以看到Word提示你恢复到以前的文档。

    模式结构

    模式结构
    1. Memento:备忘录。主要用来存储原发器对象的内部状态,但是具体需要存储哪些数据是由原发器对象来决定的。另外备忘录应该只能由原发器对象来访问它内部的数据,原发器外部的对象不应该能访问到备忘录对象的内部数据。

    2. Originator:原发器。使用备忘录来保存某个时刻原发器自身的状态,也可以使用备忘录来恢复内部状态。

    1. Caretaker:备忘录管理者,或者称为备忘录负责人。主要负责保存备忘录对象,但是不能对备忘录对象的内容进行操作或检查。

    代码实现

    UML图

    源码

    public interface FlowAMockMemento {
    }
    
    public class FlowAMock {
        private String flowName;
        private int tempResult;
        private String tempState;
    
        public FlowAMock(String flowName) {
            this.flowName = flowName;
        }
    
        public void runPhaseOne(){
            tempResult = 3;
            tempState = "phaseOne";
        }
        public void schema1(){
            this.tempState += ",Schema1";
            System.out.println(this.tempState+":now run " + tempResult);
            this.tempResult += 11;
        }
    
        public void schema2(){
            this.tempState += ",Schema2";
            System.out.println(this.tempState+":now run " + tempResult);
            this.tempResult += 22;
        }
    
        public FlowAMockMemento createMemento(){
            return new MementoImpl(this.tempResult,this.tempState);
        }
    
        public void setMemento(FlowAMockMemento memento){
            MementoImpl mementoImpl = (MementoImpl) memento;
            this.tempResult = mementoImpl.getTempResult();
            this.tempState = mementoImpl.getTempState();
        }
    
        /**
         * 真正的备忘录对象,实现备忘录窄接口
         * 实现成为私有内部类
         */
        private static class MementoImpl implements FlowAMockMemento{
            @Getter
            private int tempResult;
            @Getter
            private String tempState;
    
            public MementoImpl(int tempResult, String tempState) {
                this.tempResult = tempResult;
                this.tempState = tempState;
            }
        }
    }
    
    @Data
    public class FlowAMementoCareTaker{
    
        private FlowAMockMemento memento;
    }
    
    public class Client {
        public static void main(String[] args) {
            FlowAMock mock = new FlowAMock("testFlow");
            mock.runPhaseOne();
    
            FlowAMementoCareTaker careTaker = new FlowAMementoCareTaker();
            FlowAMockMemento memento = mock.createMemento();
            careTaker.setMemento(memento);
    
            mock.schema1();
            mock.setMemento(memento);
            mock.schema2();
        }
    }
    
    

    模式的优缺点

    模式的优点

    1. 更好的封装性

      备忘录模式通过使用备忘录对象,来封装原发器对象的内部状态,虽然这个对象是保存在原发器对象的外部,但是由于备忘录对象的窄接口并不提供任何方法,这样有效的保证了对原发器对象内部状态的封装,不把原发器对象的内部实现细节暴露给外部。

    2. 简化了原发器

      备忘录模式中,备忘录对象被保存到原发器对象之外,让客户来管理他们请求的状态,从而让原发器对象得到简化。

    3. 窄接口和宽接口

    模式的缺点

    1. 可能会导致高开销

      备忘录模式基本的功能,就是对备忘录对象的存储和恢复,它的基本实现方式就是缓存备忘录对象。这样一来,如果需要缓存的数据量很大,或者是特别频繁的创建备忘录对象,开销是很大的。

    思考

    模式本质:保存和恢复内部状态

    开发中的应用场景:

    1. 棋类游戏,悔棋

    2. 普通软件,撤销操作

    3. 数据库软件中的,事务管理的,回滚操作

    4. Photoshop软件

    相关模式

    1. 备忘录模式和命令模式
      这两个模式可以组合使用。

    命令模式实现中,在实现命令的撤销和重做的时候,可以使用备忘录模式,在命令操作的时候记录下操作前后的状态,然后在命令撤销和重做的时候,直接使用相应的备忘录对象来恢复状态就可以了。
    在这种撤销的执行顺序和重做执行顺序可控的情况下,备忘录对象还可以采用增量式记录的方式,可以减少缓存的数据量。

    1. 备忘录模式和原型模式
      这两个模式可以组合使用。

    在原发器对象创建备忘录对象的时候,如果原发器对象中全部或者大部分的状态都需要保存,一个简洁的方式就是直接克隆一个原发器对象。也就是说,这个时候备忘录对象里面存放的是一个原发器对象的实例。

    相关文章

      网友评论

          本文标题:备忘录模式

          本文链接:https://www.haomeiwen.com/subject/idivsttx.html