备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
需求
游戏的某个场景,一游戏角色有生命力、攻击力、防御力等等数据,在打Boss前和后一定会不一样的,我们允许玩家如果感觉与Boss决斗的效果不理想可以让游戏恢复到决斗前。
代码
业务类
c
#include <stdio.h>
#include <stdlib.h>
typedef struct RoleStateMemo {
int vit;
int atk;
int def;
} RoleStateMemo;
RoleStateMemo *InitRoleStateMemo(int vit, int atk, int def) {
RoleStateMemo *obj = (RoleStateMemo *)malloc(sizeof(RoleStateMemo));
obj->atk = atk;
obj->vit = vit;
obj->def = def;
return obj;
}
typedef struct PlayRole {
int vit;
int atk;
int def;
// 金币
int gold;
RoleStateMemo *(*saveState)(struct PlayRole *);
void (*recoveryState)(struct PlayRole *, RoleStateMemo *);
void (*stateDisplay)(struct PlayRole *);
void (*fight)(struct PlayRole *);
} PlayRole;
RoleStateMemo *SaveState(PlayRole *obj) {
RoleStateMemo *res = InitRoleStateMemo(obj->vit, obj->atk, obj->def);
return res;
}
void RecoveryState(PlayRole *obj, RoleStateMemo *memo) {
obj->vit = memo->vit;
obj->atk = memo->atk;
obj->def = memo->def;
return;
}
void StateDisplay(PlayRole *obj) {
printf("角色状态信息:\n");
printf("生命值:%d\n", obj->vit);
printf("攻击力:%d\n", obj->atk);
printf("防御力:%d\n", obj->def);
printf("金币:%d\n", obj->gold);
printf("======end======\n");
}
void Fight(PlayRole *obj) {
obj->vit = (obj->vit)/2;
obj->def = (obj->def)/2;
obj->gold += 100;
}
PlayRole *InitPlayRole() {
PlayRole *obj = (PlayRole *)malloc(sizeof(PlayRole));
obj->vit = 100;
obj->atk = 10;
obj->def = 10;
obj->gold = 0;
obj->saveState = SaveState;
obj->recoveryState = RecoveryState;
obj->stateDisplay = StateDisplay;
obj->fight = Fight;
return obj;
}
typedef struct RoleStateManager {
RoleStateMemo *memo;
} RoleStateManager;
客户端
c
int main() {
// 大战BOSS前
PlayRole *lixiaoyao = InitPlayRole();
lixiaoyao->stateDisplay(lixiaoyao);
// 保存进度
RoleStateManager stateManager;
stateManager.memo = lixiaoyao->saveState(lixiaoyao);
// 大战
lixiaoyao->fight(lixiaoyao);
lixiaoyao->stateDisplay(lixiaoyao);
// 恢复之前进度
lixiaoyao->recoveryState(lixiaoyao, stateManager.memo);
lixiaoyao->stateDisplay(lixiaoyao);
return 0;
}
客户端打印:
text
角色状态信息:
生命值:100
攻击力:10
防御力:10
金币:0
======end======
角色状态信息:
生命值:50
攻击力:10
防御力:5
金币:100
======end======
角色状态信息:
生命值:100
攻击力:10
防御力:10
金币:100
======end======
UML图

Originator(发起人,此处是PlayRole):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。
Memento(备忘录, 此处是RoleStateMemo):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。
Caretaker(管理者,此处是RoleStateManager):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
总结
- 备忘录模式使用场景?
"Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。"