一 使用场景
我们玩游戏时都会保存进度,所保存的进度以文件的形式存在。这样下次就可以继续玩,而不用从头开始。这里的进度其实就是游戏的内部状态,而这里的文件相当于是在游戏之外保存状态。这样,下次就可以从文件中读入保存的进度,从而恢复到原来的状态。这就是备忘录模式。
二 定义
备忘录模式 Memento Pattern:在不破坏封装的前提下,捕获一个对象的内部状体,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为型模。
Originator 原发器:它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。
Memento 备忘录:存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。
Caretaker 负责人:负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。
三 C++实现备忘录模式
GameRole.h
#pragma once
#include <iostream>
#include "RoleStateMemento.h"
using namespace std;
class GameRole
{
public:
GameRole():m_blood(100){}
RoleStateMemento * SaveState(){
return new RoleStateMemento(m_blood);
}
void RecoveryState(RoleStateMemento * _rolestate){
m_blood = _rolestate->getBloodValue();
std::cout << "recovery..." << std::endl;
}
void showState(){
std::cout << "blood: " << m_blood << std::endl;
}
void Fight(){
m_blood -= 10;
}
private:
unsigned m_blood;
};
RoleStateMemento.h
#pragma once
#include <iostream>
using namespace std;
class RoleStateMemento
{
public:
RoleStateMemento(unsigned _blood):m_blood(_blood){}
private:
friend class GameRole;
unsigned getBloodValue(){
return m_blood;
}
unsigned m_blood;
};
Caretaker.h
#pragma once
#include "RoleStateMemento.h"
class CareTaker
{
public:
CareTaker(){}
virtual ~CareTaker(){}
void setRoleStateMemento(RoleStateMemento * _sm){
state_memento = _sm;
}
RoleStateMemento * getRoleStateMemento(){
return state_memento;
}
private:
RoleStateMemento * state_memento;
};
main.cpp
#include <iostream>
#include "GameRole.h"
#include "Caretaker.h"
using namespace std;
int main()
{
GameRole * roler = new GameRole();
roler->showState();
CareTaker * caretaker = new CareTaker();
caretaker->setRoleStateMemento(roler->SaveState());
roler->Fight();
roler->showState();
roler->RecoveryState(caretaker->getRoleStateMemento());
roler->showState();
system("pause");
return 0;
}
四 总结
优点:
1 提供状态恢复机制,可以回到特定的历史步骤。
2 备忘录实现了对信息的封装,一个备忘录表示一个状态。
缺点:
1 资源消耗过大,变量多的话会不可避免的占用大量空间。