设计模式,备忘录模式:(任务失败,回到检查点重来),c++实现

备忘录模式:(任务失败,回到检查点重来)

定义
在不破坏封装性的前提下,捕捉一个对象的内部状态,并在对象之外保存这个状态,使其可以在以后将对象恢复到这个状态。

翻译
一个类需要拥有一个备份类用来记录和恢复自己在某个时刻的状态,只需要复制自己,保留数据,删去功能函数,保留构造函数后,便是一个该类的数据备份类了,
需要备份类的类的增加两个函数,是对备份类的get和set函数。

类图摘自设计模式之禅:
在这里插入图片描述

深入
但我们想要恢复某个状态时,肯定得恢复那个状态下的类以及周围受到其影响的类的状态,故备份类会和需要备份的类多起来,就需要备忘录管理类,降低类与备份类的耦合。

应用场景
应用场景太多了,文档存档,游戏存档,游戏检查点存档,项目日志存档,数据库存档,任何需要“保存”的地方都是备忘录模式发挥作用的地方。

作用
1.提供回滚操作(rollback),就是撤销或者上一步。
2.监控对象时,因监控不是系统主业务,一般是备份一个主线程的对象,然后由分析程序分析。
3.保存至数据库。

注意点
备忘录的生命周期
备忘录创建出来就是要在“最近”的代码中使用,要主动管理他的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾收集器对它的回收处理。
备忘录的性能
不能再频繁建立备份的场景中使用备忘录模式,如for循环中。一是难以控制建立的对象数量,二是建立大对象消耗的资源多。

全状态备份:保留所有状态
将发起对象的所有属性值转化到hashmap中,就是哈希表,避免直接拷贝对象,直接拷贝对象就破坏了发起人的通用性,避免在恢复动作中对该对象的多次赋值操作而产生失误。

多备份的备忘录:多次备份全状态备份
给每次备份增加一个时间点并一一对应,故只需要把原容器再通过增加时间点包装一次,做成一个map就可。
注意:备份一旦产生就会装入内存,没有任何销毁的意向,这是相当危险的,因此设计系统时,要严格限定备忘录的创建,建议增加map的上限,避免系统出现内存溢出。

代码示例:这是一个简单的备忘录模式示例,一个数据类作为备份保存一个功能类的状态,备份管理类中也只有这一中备份,实际开发中的情况并非如此,留在文尾。

//数据备份类
class Memento
{
public:
	Memento(int iData)
	{
		mData = iData;
	}

	int GetData()
	{
		return mData;
	}

protected:
	int mData;
};

//备份管理类
class CareTakerOfOriginator
{
public:
	void SetMemento(Memento * memento)
	{
		mMemento = memento;
	}

	Memento* GetMemento()
	{
		if (mMemento != nullptr)
		{
			return mMemento;
		}
		else
		{
			return nullptr;
		}
	}

protected:
	Memento* mMemento;
};

//备份发起和调用类
class Originator
{
public:
	Originator()
	{
		mData = 0;
	}

	void StatusShow()
	{
		cout << "我现在的数据状态是,数据Data值为" << mData << endl;
	}

	Memento* SetMemento()
	{
		cout << "状态已存盘" << endl;
		return (new Memento(mData));
	}

	void GetMemento(Memento* memento)
	{
		cout << "状态已读取" << endl;
		mData = memento->GetData();
	}

	void action()
	{
		cout << "数据状态发生改变" << endl;
		++mData;
	}

protected:
	int mData;
};

void func()
{
	Originator* ZhangSan = new Originator();
	CareTakerOfOriginator* ZSCareTaker = new CareTakerOfOriginator();

	ZhangSan->StatusShow();
	ZSCareTaker->SetMemento(ZhangSan->SetMemento());
	ZhangSan->action();
	ZhangSan->StatusShow();
	ZhangSan->action();
	ZhangSan->StatusShow();
	ZhangSan->action();
	ZhangSan->StatusShow();
	ZhangSan->action();
	ZhangSan->StatusShow();
	ZhangSan->action();
	ZhangSan->StatusShow();
	ZhangSan->GetMemento(ZSCareTaker->GetMemento());
	ZhangSan->StatusShow();
}

int main()
{
	func();
	return 0;
}

在这里插入图片描述
我们成功的使用备份复原了保存时的数据状态,但这只是一个简单而基础的演示,实际开发中的功能类数量,备份类数量,管理类的管理方法远远不会如此简单,基于安全性的考虑也不会将代码设计的如此简陋,实际中的数据备份是相当庞大的,占用极多资源的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值