zoukankan      html  css  js  c++  java
  • 备忘录模式

    一、概述

    一般问题:很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。

    核心方案:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

    设计意图:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。那么保存的内部状态必然要有一个内部状态类MemoryTo,存储于该对象之外,那必然要有一个管理类CareTaker。故其类图如下:

     

    备忘录模式的类图比较简单:

    • Originator——原发器
    • Memento——备忘录
    • Caretaker——备忘录管理员

    由于在备忘录中存储的是原发器的中间状态,因此需要防止原发器以外的其他对象访问备忘录。备忘录对象通常封装了原发器的部分或所有的状态信息,而且这些状态不能被其他对象访问,也就是说不能在备忘录对象之外保存原发器状态,因为暴露其内部状态将违反封装的原则,可能有损系统的可靠性和可扩展性。 


    二、应用实战

    Activity状态保存是Android中备忘录模式的典型使用,主要对应Activity的两个回调方法onSaveInstanceState()和OnRestoreInstanceState()。

    保存Activity状态onSaveInstanceState():

        protected void onSaveInstanceState(Bundle outState) {
            outState.putBundle("android:viewHierarchyState", this.mWindow.saveHierarchyState());
            outState.putInt("android:lastAutofillId", this.mLastAutofillId);
            Parcelable p = this.mFragments.saveAllState(); //Fragments保存状态
            if (p != null) {
                outState.putParcelable("android:fragments", p);
            }
    
            if (this.mAutoFillResetNeeded) {
                outState.putBoolean("@android:autofillResetNeeded", true);
                this.getAutofillManager().onSaveInstanceState(outState);
            }
    
            this.dispatchActivitySaveInstanceState(outState); //其他ActivityLifecycleCallbacks保存状态
        }

    这里的Bundle对应备忘录Memento类,View和Fragment等对应Originator原发器,Activity对应Caretaker管理者。


    三、总结

    总结:备忘录模式是一种行为型设计模式,为了实现对备忘录对象的封装,需要对备忘录的调用进行控制:

    1. 对于原发器而言,它可以调用备忘录的所有信息,允许原发器访问返回到先前状态所需的所有数据;
    2. 对于负责人而言,只负责备忘录的保存并将备忘录传递给其他对象;
    3. 对于其他对象而言,只需要从负责人处取出备忘录对象并将原发器对象的状态恢复,而无须关心备忘录的保存细节。

    用一句话概括备忘录模式:

    要后悔药吗?

    优点:

    • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态
    • 实现了信息的封装,使得用户不需要关心状态的保存细节

    缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存

  • 相关阅读:
    做题总结
    关于SQLSERVER中用SQL语句查询的一些个人理解
    关于SQLSERVER联合查询一点看法
    C#中怎样实现序列化和反序列化
    java内部类的使用
    C#抽象类
    匿名类
    Foreach能够循环的本质
    C#索引器
    深入了解接口的使用
  • 原文地址:https://www.cnblogs.com/not2/p/11091363.html
Copyright © 2011-2022 走看看