设计模式之备忘录模式
Posted tobeexpert
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之备忘录模式相关的知识,希望对你有一定的参考价值。
2018-09-22 22:35:23
备忘录模式
备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原来保存的状态。
备忘录模式UML类图
Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可以使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。
Memento(备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其它对象访问备忘录Memento。备忘录有两个接口,Cartaker只能看到备忘录的窄接口,它只能将备忘录传递给其它对象。Originator能看到一个宽接口,允许它访问返回到先前状态所需的所有数据。
Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或者检查。
优缺点
优点:
1.提供了一种状态恢复机制,把要保存的细节封装在了Memento中,使用户能够方便的回到某个历史状态,如果需要更改保存的细节,也不会对客户端产生影响。
2.实现了信息的封装,使用户不需要关心保存信息的细节。
缺点:
1.角色状态需要完整存储到备忘录对象中,如果状态数据很多很大,那么在资源消耗上,备忘录对象会非常消耗内存。
适用场景:
Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态,有时一些对象的内部信息必须保存在对象以外的地方,但是必须由对象自己读取,这是使用备忘录可以把复杂的对象内部信息对其它的对象屏蔽起来。作用是,当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
代码示例
(都是《大话设计模式》这本书的内容呀)背景:游戏进度备忘。假设我们需要保存的游戏角色的属性有:蓝量、血量、以及攻击力、防御力四个。
1.Originator类。打游戏的时候只有角色自己拥有恢复存档和保存进度的能力
#ifndef ORIGINATOR_H_ #define ORIGINATOR_H_ //这个类在本例中是游戏角色类 //假设你正在玩某个游戏,回忆一下,具有存档和读取存档数据的是不是只有你的游戏角色呢? #include "Memento.h" #include <string> #include <iostream> class Originator { public: Memento createMemento() { return Memento(m_iLifeValues,m_iMP,m_iATK,m_iDef); //创建一个备忘录,将当前需要保存的信息导入,并实例化出一个Memento对象 } //从备忘录中恢复存档(为什么需要这个函数呢,你想一下,你在存档之后,下机了,下次再登录进入游戏,要恢复存档,数据必然要从某个地方读入,所以这个函数是必须的 void restoreMemento(Memento objMemento) { m_iLifeValues = objMemento.getLifeValues(); m_iMP = objMemento.getMP(); m_iATK = objMemento.getATK(); m_iDef = objMemento.getDef(); } //显示属性值 void show() const { std::cout << "Name: " << m_strRoleName << " LifeValues:" << m_iLifeValues << " MP:" << m_iMP << " ATK:" << m_iATK << " Def:" << m_iDef <<std::endl; } //设置属性的初始值 void setInit(const int iLifeValues,const int iMP,const int iATK, const int iDef) { m_iLifeValues = iLifeValues; m_iMP = iMP; m_iATK = iATK; m_iDef = iDef; } //和Boss玩玩,给你一下各项属性减去100(随便写的,所以结果可能出现负值) //返回值为false,则表示Game over bool beatAMonster() { m_iLifeValues -=100; m_iMP -= 100; m_iATK -=100; m_iDef -=100; if(0>= m_iLifeValues) { return false; } return true; } Originator(const std::string strRoleName) : m_strRoleName(strRoleName){}; ~Originator() = default; private: //游戏角色的属性:生命值、魔法值、攻击力、防御力 int m_iLifeValues{0}; //生命值 int m_iMP{0}; //魔法值 int m_iATK{0}; //攻击力 int m_iDef{0}; //防御值 std::string m_strRoleName; }; #endif
2.Mementor类。备忘录,用于保存Originator类内部状态的外部类
#ifndef MEMENTO_H_ #define MEMENTO_H_ //备忘录类,负责保存属性 class Memento { public: //读取存档生命值 int getLifeValues() const { return m_iLifeValues; } //读取魔法存档值 int getMP() const { return m_iMP; } //读取攻击力存档 int getATK() const { return m_iATK; } //读取防御力存档 int getDef() const { return m_iDef; } Memento(const int iLifeValues,const int iMP,const int iATK,const int iDef):m_iLifeValues(iLifeValues),m_iMP(iMP),m_iATK(iATK),m_iDef(iDef){}; Memento(const Memento& objMemento) { m_iLifeValues = objMemento.getLifeValues(); m_iMP = objMemento.getMP(); m_iATK = objMemento.getATK(); m_iDef = objMemento.getDef(); } Memento() = default; ~Memento() = default; private: int m_iLifeValues{0}; //生命值 int m_iMP{0}; //魔法值 int m_iATK{0}; //攻击力 int m_iDef{0}; //防御力 }; #endif
3.Caretaker类。备忘录的管理类。
#ifndef CARETAKER_H_ #define CARETAKER_H_ //管理者,这个类用来管理备忘录,它的作用,就是从加载备忘录的内容,将其恢复到某个对象 #include "Memento.h" class Caretaker { public: //设置备忘录 void setMemento(Memento objMemento) { m_Memento = objMemento; } Memento getMemento() { return m_Memento; } private: Memento m_Memento; //持有一个备忘录对象,它是Caretaker进行备忘录管理的关键 }; #endif
4.client
#include "Caretaker.h" #include "Originator.h" using namespace std; int main(int argc,char *argv[]) { //创建一个游戏角色 Originator objOriginator("ChongLou"); //设置初始属性 objOriginator.setInit(100,100,100,100); //保存初始状态 Caretaker objCaretaker; objCaretaker.setMemento(objOriginator.createMemento()); //显示初始状态 objOriginator.show(); //开始打怪 objOriginator.beatAMonster(); //显示打怪后的属性 objOriginator.show(); //加载存档 objOriginator.restoreMemento(objCaretaker.getMemento()); //显示加载存档后的属性 objOriginator.show(); return(1); }
以上是关于设计模式之备忘录模式的主要内容,如果未能解决你的问题,请参考以下文章
JAVA SCRIPT设计模式--行为型--设计模式之Memnto备忘录模式(18)