设计模式(二十)——备忘录模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式(二十)——备忘录模式相关的知识,希望对你有一定的参考价值。
设计模式(二十)——备忘录模式
一、备忘录模式
1、备忘录模式简介
备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,以后就可将对象恢复到原先保存的状态。
2、备忘录模式角色
发起人Originator:负责创建一个Memento,用以记录当前时刻Originator的内部状态,并可使用Memento恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。Originator记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
备忘录Memento:负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,Caretaker只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许Originator访问返回到先前状态所需的所有数据。Memento负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
管理者Caretaker:负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。Caretaker对备忘录进行管理,保存和提供备忘录。
Memento模式中封装的是需要保存的状态,当需要恢复的时候才取出来进行恢复。Memento角色有两个接口:窄接口和宽接口。宽接口是一般意义上的接口,把对外的接口作为public成员,而窄接口把接口作为private成员,而把需要访问窄接口函数的类作为Memento类的友元类,即窄接口只暴露给了对窄接口感兴趣的类,而不是暴露在外部。
Memento模式比较适用于功能比较复杂的,但需要维护或记录历史属性的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。
3、备忘录模式优缺点
备忘录模式的优点:
A、当发起人中的状态改变时,有可能是个错误的改变,使用备忘录模式就可以把错误的改变还原。
B、备份的状态是保存在发起人之外的,发起人就不需要对各个备份的状态进行管理。
备忘录模式的缺点:
在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。
4、备忘录模式使用场景
如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如JDBC的事务操作,文本编辑器的Ctrl+Z恢复等。
二、备忘录模式实现
Originator发起人:
#ifndef ORIGINATOR_H #define ORIGINATOR_H #include "Memento.h" #include <iostream> using namespace std; //Originator发起人 class Originator { public: Originator(const string& state) { m_state = state; } Memento* createMemento() { return new Memento(m_state); } void restoreToMemento(Memento* memento) { m_state = memento->getState(); } void setState(const string& state) { m_state = state; } string getState() { return m_state; } void show() { cout << m_state << endl; } private: string m_state; }; #endif // ORIGINATOR_H
Memento备忘录:
#ifndef MEMENTO_H #define MEMENTO_H #include <string> using namespace std; //Memento class Memento { private: //Originator为friend类,可以访问内部信息,但是其他类不能访问 friend class Originator; Memento(const string& state) { m_state = state; } void setState(const string& state) { m_state = state; } string getState() { return m_state; } private: string m_state; }; #endif // MEMENTO_H
Caretaker管理者:
#ifndef CARETAKER_H #define CARETAKER_H #include "Memento.h" //Caretaker管理者 class Caretaker { public: void setMemento(Memento* memento) { m_pMemento = memento; } Memento* getMemento() { return m_pMemento; } private: Memento* m_pMemento; }; #endif // CARETAKER_H
客户调用程序:
#include "Memento.h" #include "Originator.h" #include "Caretaker.h" int main() { //创建初始状态为old Originator* originator = new Originator("old"); originator->show(); //建立并保存Memento Caretaker* taker = new Caretaker(); taker->setMemento(originator->createMemento()); //改变状态为new originator->setState("new"); originator->show(); //恢复状态 originator->restoreToMemento(taker->getMemento()); originator->show(); return 0; }
三、备忘录模式实例
玩游戏时都会保存进度,所保存的进度以文件的形式存在。下次就可以继续玩,而不用从头开始。进度其实就是游戏的内部状态,而文件是在游戏之外保存状态。下次可以从文件中读入保存的进度,从而恢复到原来的状态。
GameRole发起人:
#ifndef GAMEROLE_H #define GAMEROLE_H #include "Memento.h" #include <iostream> using namespace std; //发起人 class GameRole { public: void initState() { m_vitality = 100; m_attack = 100; m_defense = 100; } void fight() { m_vitality -= 30; m_attack -= 50; m_defense -= 40; } void setVitality(unsigned int vitality) { m_vitality = vitality; } unsigned int getVitality() { return m_vitality; } void setAttack(unsigned int attack) { m_attack = attack; } unsigned int getAttack() { return m_attack; } void setDefense(unsigned int defense) { m_defense = defense; } unsigned int getDefense() { return m_defense; } void show() { cout << "State at current:" << endl; cout << " Vitality: " << m_vitality << endl; cout << " Attack: " << m_attack << endl; cout << " Defense: " << m_defense << endl; } //创建备忘录 Memento* createMemento() { return new Memento(m_vitality, m_attack, m_defense); } //从备忘录恢复状态 void restoreFromMemento(Memento* memento) { m_vitality = memento->getVitality(); m_attack = memento->getAttack(); m_defense = memento->getDefense(); } private: unsigned int m_vitality;//生命力 unsigned int m_attack;//攻击力 unsigned int m_defense;//防御力 }; #endif // GAMEROLE_H
Memento备忘录:
#ifndef MEMENTO_H #define MEMENTO_H //备忘录 class Memento { friend class GameRole; private: Memento(unsigned int vitality,unsigned int attack,unsigned int defense) { m_vitality = vitality; m_attack = attack; m_defense = defense; } void setVitality(unsigned int vitality) { m_vitality = vitality; } unsigned int getVitality() { return m_vitality; } void setAttack(unsigned int attack) { m_attack = attack; } unsigned int getAttack() { return m_attack; } void setDefense(unsigned int defense) { m_defense = defense; } unsigned int getDefense() { return m_defense; } private: unsigned int m_vitality; unsigned int m_attack; unsigned int m_defense; }; #endif // MEMENTO_H
CareTaker管理者:
#ifndef CARETAKER_H #define CARETAKER_H #include "Memento.h" #include <iostream> //管理者 class CareTaker { public: ~CareTaker() { if(m_pMemento != NULL) { delete m_pMemento; m_pMemento = NULL; } } Memento* GetMemento() { return m_pMemento; } void SetMemento(Memento* memento) { m_pMemento = memento; } private: Memento* m_pMemento; }; #endif // CARETAKER_H
客户调用程序:
#include "GameRole.h" #include "CareTaker.h" #include "Memento.h" int main() { //攻击之前 GameRole* role = new GameRole(); role->initState(); role->show(); //保存进度 CareTaker* taker=new CareTaker(); taker->SetMemento(role->createMemento()); //开战,损耗严重 role->fight(); role->show(); //恢复开战前状态 role->restoreFromMemento(taker->GetMemento()); role->show(); delete role; delete taker; return 0; }
本文出自 “生命不息,奋斗不止” 博客,谢绝转载!
以上是关于设计模式(二十)——备忘录模式的主要内容,如果未能解决你的问题,请参考以下文章