程序设计模式结课论文
发布时间:2015-01-26 18:48:16
发布时间:2015-01-26 18:48:16
河南理工大学
《程序设计模式》结课论文
2012 — 2013学年 第二学期
论文题目 设计模式之备忘录模式
学生姓名
学 号
专业班级
指导教师
201x 年 6月 13 日
备忘录模式
1.模式背景
有一首歌叫做《如果再回到从前》,相信大家一定听过。时光如果可以倒流,那么很多时候做的错误的决定或者选择就可以回到去过,撤销并重做,这是一件多么好的事情啊!
还记得玩单机PC游戏时,通常在打BOSS前都要先保存一个进度,如果失败了还可以回到刚才的那个进度,从头再来。很多现实里无法实现的事情在软件中就可以实现,而这正是设计应用软件时常用的基本思想——保存备忘录。
2.模式动机与意图
为了使软件的使用更加人性化,对于误操作,我们需要提供一种类似“后悔药”的机制,让软件系统可以回到误操作前的状态,因此需要保存用户每一次操作时系统的状态,一旦出现误操作,可以把存储的历史状态取出即可回到之前的状态。
现在大多数软件都有撤销(Undo)的功能,快捷键一般都是Ctrl+Z,目的就是为了解决这个后悔的问题。
在此以游戏进度保存为例子,在游戏的某个场景,以游戏角色有生命力、攻击力、防御力等等数据,在打BOSS前和后一定会不一样。因此,实现游戏当前内容的保存,在感觉打不过BOSS时,允许回到游戏存档时的状态。
为了实现这一功能,我们要使用备忘录模式。
3.模式定义
备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
4.结构图
4.1备忘录模式
4.1.1备忘录模式结构图
4.1.2模式分析
由于在备忘录中存储的是原发器的中间状态,因此需要防止原发器以外的其他对象访问备忘录。
备忘录对象通常封装了原发器的部分或所有的状态信息,而且这些状态不能被其他对象访问,也就是说不能在备忘录对象之外保存原发器状态,因为暴露其内部状态将违反封装的原则,可能有损系统的可靠性和可扩展性。
4.1.3备忘录模式的优点
提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用先前存储起来的备忘录将状态复原。
实现了信息的封装,一个备忘录对象是一种原发器对象的表示,不会被其他代码改动,这种模式简化了原发器对象,备忘录只保存原发器的状态,采用堆栈来存储备忘录对象可以实现多次撤销操作,可以通过在负责人中定义集合对象来存储多个备忘录。
4.1.4备忘录模式的缺点
资源消耗过大,如果类的成员变量太多,就不可避免占用大量的内存,而且每保存一次对象的状态都需要消耗内存资源,如果知道这一点大家就容易理解为什么一些提供了撤销功能的软件在运行时所需的内存和硬盘空间比较大了。
4.2当前例子结构图
Originator(游戏角色):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复它的状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。
Memento(备忘存档):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。
5.代码实现
Originator 游戏角色类
class Originator
{
private int vit;
private int atk;
private int def;
//初始化角色
public void GetInitState()
{
vit = 100;
atk = 100;
def = 100;
}
//显示角色状态
public void StateDisplay()
{
Console.WriteLine("角色状态为:" + "\n"+"生命值:"+vit+"\n"+"攻击力:"+atk+"\n"+"防御力:"+def);
}
//保存游戏状态
public RoleStateMemento SaveState()
{
return (new RoleStateMemento(vit,atk,def));
}
//恢复角色状态
public void RecoveryState(RoleStateMemento memento)
{
this.vit = memento.Vitality;
this.atk = memento.Attack;
this.def = memento.Defense;
}
//角色战斗打BOSS
public void Fight()
{
vit -= 50;
}
}
RoleStateMemento 角色状态存储类
class RoleStateMemento
{
private int vit;
private int atk;
private int def;
public RoleStateMemento(int vit,int atk,int def)
{
this.vit = vit;
this.atk = atk;
this.def = def;
}
//生命力
public int Vitality
{
get;
set;
}
//攻击力
public int Attack
{
get;
set;
}
//防御力
public int Defense
{
get;
set;
}
}
RoleStateCaretaker 游戏状态管理者类
class RoleStateCaretaker
{
private RoleStateMemento memento;
public RoleStateMemento Memento
{
get;
set;
}
}
Client 客户端
class Client
{
static void Main(string[] args)
{
//大战前
Originator lixiaoyao = new Originator();
lixiaoyao.GetInitState();
lixiaoyao.StateDisplay();
//保存进度
RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
stateAdmin.Memento = lixiaoyao.SaveState();
//大战BOSS
lixiaoyao.Fight();
lixiaoyao.StateDisplay();
//恢复之前状态
lixiaoyao.RecoveryState(stateAdmin.Memento);
lixiaoyao.StateDisplay();
Console.ReadKey();
}
}
6.总结
6.1模式总结
在备忘录模式中,包含至少三个角色:原发器可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态;备忘录存储原发器的内部状态,根据原发器来决定保存哪些内部状态;负责人负责保存备忘录,但是不能对备忘录的内容进行操作或检查。
备忘录对象通常封装了原发器的部分或所有的状态信息,而且这些状态不能被其他对象访问,也就是说不能在该对象之外保存其状态,因为暴露其内部状态将违反封装的原则,可能有损系统的可靠性和可扩展性。
备忘录模式的主要优点在于它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,还简化了原发器对象,备忘录只保存原发器的状态,采用堆栈来存储备忘录对象可以实现多次撤消操作,可以通过在负责人中定义集合对象来存储多个备忘录;备忘录模式的主要缺点在于资源消耗过大,因为每一个历史状态的保存都需要一个备忘录对象。
备忘录模式适用情况包括:保存一个对象在某一个时刻的状态或部分状态,这样以后需要时它能够恢复到先前的状态;如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
6.2实例总结
在上面的游戏角色例子中,使用了3个类,这符合备忘录模式的结构。游戏角色负责角色的基本创建,包括角色的属性、行为、存档读档的功能。然后在角色状态存储类中也相应的设置了一些角色的相关属性,用来保存角色属性变化时的值。
但是,例子中只是保存了角色的一些属性值,这只是角色状态的一部分,而状态还应该包含游戏角色周围的状态,这当然是在大型的游戏中需要考虑的。并且,值得注意的是,有时候我们不一定要保存一个角色的所有属性或者状态,有可能我们只是想保存一下它当前的地理位置、基本属性值或者仅仅是一个简单的角色设置,而这,都不是以上例子所能实现的,因此,还需要对角色类、角色存储类的结构进行改进。