Android编程设计模式之备忘录模式详解
作者:蹲街式等待 发布时间:2023-06-29 14:55:15
本文实例讲述了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程序设计有所帮助。
来源:http://blog.csdn.net/wangzhongshun/article/details/78397051


猜你喜欢
- 一、参数管理在编程系统中,为了能写出良好的代码,会根据是各种设计模式、原则、约束等去规范代码,从而提高代码的可读性、复用性、可修改,实际上个
- 对上次的三个问题的个人理解: 1) 程序首先是从main函数开始执行的,假设main 函数不是 static ,就要先实例化这个类,然后调用
- 本文实例分析了Android中ImageView用法。分享给大家供大家参考,具体如下:猜牌游戏大家可能以前都玩过,这里我们用这个小游戏来说明
- from jnius import autoclass>>> Stack = autoclass('java.ut
- 一、进程与线程的概念(1)在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单位都是进程。在未配置 OS 的系统中,程序的
- 使用Post添加数据到数据库出现方块乱码解决方法,在web.xml里最前面添加过滤器,代码如下,放在最前面,因为有优先级,要首先拦截<
- String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要
- 稀疏数组:当一个二维数组中大部份的值为0,或者为同一值的时候,可以用稀疏数组来保存实现思路:记录二维数组有多少行多少列、多少个不同的值把不同
- Word中设置水印时,可使用预设的文字或自定义文字设置为水印效果,但通常添加水印效果时,会对所有页面都设置成统一效果,如果需要对每一页或者某
- android原生的下拉框Spinner基本上可以满足Android开发对于下拉选项的设计需求,但现在越来越流行的下拉框不满足于Androi
- 本文实例为大家分享了Android实现简单手电筒功能的具体代码,供大家参考,具体内容如下XML:<?xml version="
- List接口介绍—ArrayList有序、可重复线程不安全,因为没有synchronized修饰ArrayList源码结论ArrayList
- java中找不到符号问题 java找不到符号如果你的代码里没有报错,明明是存在的。但是java报错找不到符号。像下面这样子。解决步
- C#实现MD5加密,具体如下:方法一首先,先简单介绍一下MD5MD5的全称是message-digest algorithm 5(信息-摘要
- 引言在性能测试过程中,验证HTTP code和响应业务code码是比较基础的,但是在一些业务中,这些参数并不能保证接口正常响应了,很可能返回
- 一般文本文件我们以日志文件.log文件为例:import java.io.BufferedReader; import java.io.Fi
- 本文实例为大家分享了Drawerlayout侧滑菜单的具体代码,供大家参考,具体内容如下1、Drawerlayout的xml布局<?x
- 环境:SpringBoot 2.0.4.RELEASE需求:很多Controller方法,刚进来要先获取当前登录用户的信息,以便做后续的用户
- 废话不多说了,直接给大家贴代码,具体代码如下所示://打开Excel文件,转换为DataTable DataTable dtExcel;pr
- 前言本文主要给大家介绍了关于JDK8新增的原子性操作类LongAdder的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的