热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android编程设计模式之备忘录模式详解

这篇文章主要介绍了Android编程设计模式之备忘录模式,结合实例形式详细分析了Android备忘录模式的概念、原理、应用场景、用法及相关操作注意事项,需要的朋友可以参考下

本文实例讲述了Android编程设计模式之备忘录模式。分享给大家供大家参考,具体如下:

一、介绍

备忘录模式是一种行为模式,该模式用于保存对象当前状态,并且在之后可以再次恢复到此状态,这有点像我们平时说的”后悔药“。备忘录模式实现的方式需要保证被保存的对象状态不能被对象从外部访问,目的是为了保护好被保存的这些对象状态的完整性以及内部实现不向外暴露。

二、定义

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

三、使用场景

需要保存一个对象在某一个时刻的状态或部分状态。

如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访问其内部状态。

四、备忘录模式的UML类图

UML类图:

角色介绍:

Originator:负责创建一个备忘录,可以记录、恢复自身的内部状态。同时Originator还可以根据需要决定Memento存储自身的哪些内部状态。

Memento:备忘录角色,用于存储Originator的内部状态,并且可以防止Originator以外的对象访问Memento。

Caretaker:负责存储备忘录,不能对备忘录的内容进行操作和访问,只能将备忘录传递给其他对象。

五、简单示例

对备忘录模式来说,比较贴切的场景应该是游戏中的存档功能,该功能就是将游戏进度存储到本地文件系统或数据库中,下次再次进入时从本地加载进度,使得玩家能够继续上一次的游戏之旅,这里我们就以”使命召唤“这款游戏为例来简单演示一下备忘录模式的实现。

首先我们建立游戏类、备忘录类、Caretaker类,玩游戏到某个节点对游戏进行存档,然后退出游戏,再重新进入时从存档中读取进行,并且进入存档时的进度。

游戏类:

/**
 *
 * 简单模拟“使命召唤”游戏
 *
 */
public class CallOfDuty {
  private int mCheckpoint = 1;
  private int mLiftValue = 100;
  private String mWeapon = "沙漠之鹰";
  //玩游戏
  public void play(){
    System.out.println("打游戏:"+String.format("第%d关", mCheckpoint) + "奋战杀敌中");
    mLiftValue -= 10;
    System.out.println("进度升级了");
    mCheckpoint++;
    System.out.println("到达" + String.format("第%d关", mCheckpoint));
  }
  //退出游戏
  public void quit(){
    System.out.println("--------------");
    System.out.println("退出前的游戏属性:" + this.toString());
    System.out.println("退出游戏");
    System.out.println("--------------");
  }
  /**
   *创建备忘录
   */
  public Memento createMemento(){
    Memento memento = new Memento();
    memento.mCheckpoint = mCheckpoint;
    memento.mLiftValue = mLiftValue;
    memento.mWeapon = mWeapon;
    return memento;
  }
  //恢复游戏
  public void restore(Memento memento){
    this.mCheckpoint = memento.mCheckpoint;
    this.mLiftValue = memento.mLiftValue;
    this.mWeapon = memento.mWeapon;
    System.out.println("恢复后的游戏属性:" + this.toString());
  }
  //省略getter和setter方法
  @Override
  public String toString() {
    return "CallOfDuty [mCheckpoint=" + mCheckpoint + ",mLiftValue="
        + mLiftValue + ",mWeapon=" + mWeapon + "]";
  }
}

在CallOfDuty游戏类中,我们存储了几个关键字段,关卡、人物的生命值、武器,当调用play函数玩游戏时,我们对关卡和人物的生命值进行修改。在该类中可以通过createMemoto函数来创建该用户的备忘录对象,也就是将自身的状态保存到一个Memoto对象中。外部可以通过restore函数将CallOfDuty对象的状态从备忘录对象中恢复。

我们在来看下备忘录对象,它只是存储CallOfDuty对象的字段,具体代码如下:

备忘录类:

/**
 * 备忘录类
 */
public class Memento {
  public int mCheckpoint;//武器
  public int mLiftValue;//生命
  public String mWeapon;//关卡
  @Override
  public String toString() {
    return "Memento [mCheckpoint=" + mCheckpoint + ",mLiftValue="
        + mLiftValue + ",mWeapon=" + mWeapon + "]";
  }
}

这是一个无状态、无操作的实体类,只负责用来存储Originator角色的一些数据,防止外部直接访问Originator。

而备忘录的操作者则是Caretaker角色,我们看下相关代码:

Caretaker类:

/**
 * Caretaker,负责管理Memento
 */
public class Caretaker {
  Memento mMemento; //备忘录
  /**
   * 存档
   */
  public void archive(Memento memento){
    this.mMemento = memento;
  }
  /**
   * 获取存档
   */
  public Memento getMemento(){
    return mMemento;
  }
}

Caretaker类的职责很简单,就是负责管理Memoto对象,也就是备忘录对象。

客户端类:

public class Client {
  public static void main(String[] args) {
    //构建游戏对象
    CallOfDuty game = new CallOfDuty();
    //1.打游戏
    game.play();
    Caretaker caretaker = new Caretaker();
    //2.游戏存档
    caretaker.archive(game.createMemento());
    //3.退出游戏
    game.quit();
    //4.恢复游戏
    CallOfDuty newGame = new CallOfDuty();
    newGame.restore(caretaker.getMemento());
  }
}

结果:

打游戏:第1关奋战杀敌中
进度升级了
到达第2关
--------------
退出前的游戏属性:CallOfDuty [mCheckpoint=2,mLiftValue=90,mWeapon=沙漠之鹰]
退出游戏
--------------
恢复后的游戏属性:CallOfDuty [mCheckpoint=2,mLiftValue=90,mWeapon=沙漠之鹰]
打游戏:第2关奋战杀敌中

上述过程大致有如下4步:

(1)开始游戏,闯关升级;
(2)游戏退出之前进行存档;
(3)退出游戏;
(4)重新启动游戏,从存档中恢复游戏进度。

CallOfDuty在这里为Originator角色,也就是需要存储数据的对象,在这里并没有直接存储CallOfDuty的对象,而是通过Memoto对CallOfDuty对象的数据进行存储,然后在存储Memoto对象,最终对Memoto的存取操作则交给Caretaker对象。在这个过程中,各个角色职责清晰、单一,代码也比较简单,即对外屏蔽了对CallOfDuty角色的直接访问,在满足了对象状态存取功能的同时也使得该模块的结构保持清晰、整洁。

六、Android源码中的备忘录模式

1、onSaveInstanceState和onRestoreInstanceState

当Activity不是正常方式退出,且Activity在随后的时间内被系统杀死之前会调用这两个方法让开发人员可以有机会存储Activity相关信息,且在下次返回Activity时恢复这些数据。通过这两个函数。开发人员能够在某些特殊场景下储存与界面相关的信息,提升用户体验。

七、总结

备忘录模式是在不破坏封装的条件下,通过备忘录对象(Memoto)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。

优点:

给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史状态。

实现了信息的封装,使用户不需要关心状态的保存细节。

缺点:

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

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。


推荐阅读
  • 本文介绍了在Ubuntu下制作deb安装包及离线安装包的方法,通过备份/var/cache/apt/archives文件夹中的安装包,并建立包列表及依赖信息文件,添加本地源,更新源列表,可以在没有网络的情况下更新系统。同时提供了命令示例和资源下载链接。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 仙贝旅行是日本最大的旅游服务平台之一,为广大用户提供优质的日本定制游服务。随着用户数量的增长,仙贝旅行决定与智齿科技合作,全面替换原有客服系统,打造全新的在线客服体系。该体系具备多渠道快速接入的能力,让仙贝旅行轻松与各个渠道的接入用户完成沟通。同时,机器人与人工协同发力,提升客户服务水平。 ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了StartingzookeeperFAILEDTOSTART相关的知识,希望对你有一定的参考价值。下载路径:https://ar ... [详细]
  • ubuntu用sqoop将数据从hive导入mysql时,命令: ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • SAP羞辱国产软件商:技术停在10年前
    SAP中国研究院总裁芮祥麟表示,国产软件厂商过于热衷概念炒作,技术水平停留在10年前的客户端架构水平。他认为,国内厂商推出基于SOA的产品或转型SAAS模式是不可能的,研发新架构需要时间。当前最热门的概念是云计算,芮祥麟呼吁国产厂商应该潜心研发底层架构。 ... [详细]
  • IT方面的论坛太多了,有综合,有专业,有行业,在各个论坛里混了几年,体会颇深,以前是论坛哪里人多 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • 本文讲述了孙悟空写给白骨精的信件引发的思考和反省。孙悟空在信中对自己的行为进行了反思,认识到自己胡闹的行为并没有给他带来实际的收获。他也揭示了西天取经的真相,认为这是玉皇、菩萨设下的一场陷阱。他还提到了师傅的虚伪和对自己的实心话,以及自己作为师傅准备提拔的对象而被派下来锻炼的经历。他认为路上的九九八十一难也都是菩萨算计好的,唐僧并没有真正的危险。最后,他提到了观音菩萨在关键时刻的指导。这封信件引发了孙悟空对自己行为的思考和反省,对西天取经的目的和自己的角色有了更深入的认识。 ... [详细]
  • Windows2003 IIS上设置301定向,实现不带www域名跳转带www域名的方法
    打开IIS,建一个网站,主机头用不带www的域名,随便指向一个目录。然后在这个网站上点右键,属性--主目录--重定向到URL如图ÿ ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
author-avatar
鸳鸯520_205
这个家伙很懒,什么也没留下!
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有