菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
206
0

备忘录模式

原创
05/13 14:22
阅读数 83606

一、概述

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

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

设计意图:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。那么保存的内部状态必然要有一个内部状态类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. 对于其他对象而言,只需要从负责人处取出备忘录对象并将原发器对象的状态恢复,而无须关心备忘录的保存细节。

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

要后悔药吗?

优点:

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

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

 

发表评论

0/200
206 点赞
0 评论
收藏