介绍
备忘录(Memento):在不破坏封装性的前提下,捕获- - 个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
- Originator发起人角色
记录当前时刻的内部状态, 负责定义哪些属于备份范围的状态, 负责创建和恢复备忘录数据。 - Memento备忘录角色
负责存储Originator发起人对象的内部状态, 在需要的时候提供发起人需要的内部状态。 - Caretaker备忘录管理员角色
对备忘录进行管理、 保存和提供备忘录。
应用:
- 需要保存和恢复数据的相关状态场景
- 提供一个可回滚(rollback) 的操作; 比如Word中的CTRL+Z组合键, IE浏览器中的后退按钮, 文件管理器上的backspace键等
- 需要监控的副本场景中。 例如要监控一个对象的属性, 但是监控又不应该作为系统的主业务来调用, 它只是边缘应用, 即使出现监控不准、 错误报警也影响不大, 因此一般的做法是备份一个主线程中的对象, 然后由分析程序来分析
- 数据库连接的事务管理就是用的备忘录模式
UML类图:
简单实现:
#ifndef SIMPLE_MEMENTO_H
#define SIMPLE_MEMENTO_H
#include <iostream>
using namespace std;
/**
* @brief The Memento class
* 备忘录类
* Memento (备忘录):负责存储Originator对象的内部状态,并可防止Originator 以外的其他对象访
* 问备忘录Memento。备忘录有两个接口,Caretaker 只能看到备忘录的窄接口,它只能将备忘录传递给其
* 他对象。Originator 能够看到-一个宽接口,允许它访问返回到先前状态所需的所有数据。
*/
class Memento
{
public:
Memento(const string &state)
{
m_state = state;
}
string getState() const
{
return m_state;
}
void setState(const string &state)
{
m_state = state;
}
private:
string m_state;
};
/**
* @brief The Originator class
* 发起人类
* Originator (发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用
* 备忘录恢复内部状态。Originator 可根据需要决定Memento存储Originator的哪些内部状态。
*/
class Originator
{
public:
string getState() const
{
return m_state;
}
void setState(const string &state)
{
m_state = state;
}
Memento* createMemento() const
{
return (new Memento(m_state));
}
void setMemento(const Memento *mem)
{
m_state = mem->getState();
}
void show()
{
cout<<" State = "<<m_state<<endl;
}
private:
string m_state;
};
/**
* @brief The Caretaker class
* Caretaker (管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
*/
class Caretaker
{
public:
void setMemento( Memento *mem)
{
m_mem = mem;
}
Memento * getMemento() const
{
return m_mem;
}
private:
Memento *m_mem;
};
#endif // SIMPLE_MEMENTO_H
调用:
//Originator初始状态,状态属性位“ON”
Originator *o = new Originator;
o->setState("ON");
o->show();
Caretaker *c = new Caretaker;
//保存状态时,由于有了狠好的封装,可以隐藏Originator的实现细节
c->setMemento(o->createMemento());
//Originator改变了状态属性为:“OFF”
o->setState("OFF");
o->show();
//还原初始状态
o->setMemento(c->getMemento());
o->show();
delete o;
delete c;
大话设计模式第18章游戏保存例子:
UML类图:
#ifndef GAME_MEMENTO_H
#define GAME_MEMENTO_H
#include <iostream>
using namespace std;
class RoleStateMemento
{
public:
RoleStateMemento(int vit , int atk , int def)
{
m_vit = vit;
m_atk = atk;
m_def = def;
}
//生命力
int getVitality() const
{
return m_vit;
}
void setVitality(const int &vit)
{
m_vit = vit;
}
//攻击力
int getAttack() const
{
return m_atk;
}
void setAttack(const int &atk)
{
m_atk = atk;
}
//防御力
int getDefense() const
{
return m_def;
}
void setDefense(const int &def)
{
m_def = def;
}
private:
int m_vit;
int m_atk;
int m_def;
};
class GameRoleOriginator
{
public:
//生命力
int getVitality() const
{
return m_vit;
}
void setVitality(const int &vit)
{
m_vit = vit;
}
//攻击力
int getAttack() const
{
return m_atk;
}
void setAttack(const int &atk)
{
m_atk = atk;
}
//防御力
int getDefense() const
{
return m_def;
}
void setDefense(const int &def)
{
m_def = def;
}
RoleStateMemento* saveStateMemento() const
{
return (new RoleStateMemento(m_vit , m_atk , m_def));
}
void recoveryState(const RoleStateMemento *mem)
{
m_vit = mem->getVitality();
m_atk = mem->getAttack();
m_def = mem->getDefense();
}
void show()
{
cout<<"角色当前状态:"<<endl;
cout<<"生命力:"<<m_vit<<endl;
cout<<"攻击力:"<<m_atk<<endl;
cout<<"防御力:"<<m_def<<endl;
cout<<"---------------------\n";
}
//初始状态
void getInitState()
{
m_vit = 100;
m_atk = 100;
m_def = 100;
}
//战斗
void fight()
{
m_vit = 0;
m_atk = 0;
m_def = 0;
}
private:
int m_vit;
int m_atk;
int m_def;
};
class RoleStateCaretaker
{
public:
void setRSM(RoleStateMemento *rsm)
{
m_roleState = rsm;
}
RoleStateMemento *getRSM() const
{
return m_roleState;
}
private:
RoleStateMemento *m_roleState;
};
#endif // GAME_MEMENTO_H
调用:
//大战Boss前
GameRoleOriginator *gro = new GameRoleOriginator;
gro->getInitState();
gro->show();
//保存进度
RoleStateCaretaker *stateAdmin = new RoleStateCaretaker;
stateAdmin->setRSM(gro->saveStateMemento());
//大战boss时,损耗严重
gro->fight();
gro->show();
//恢复之前的状态
gro->recoveryState(stateAdmin->getRSM());
gro->show();