设计模式--备忘录模式

设计模式–备忘录模式


备忘录模式

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可对该对象恢复到原来的状态。

在玩象棋或者五子棋的时候,常会遇到要悔棋情况,一步二步还好,可以记下来,但是如果从一开始就把所有走的步骤都记下来,属实很困难(不仅仅下棋,就比如我们编程所用的编译器,excel,word等等,都有撤销还原的功能)。现在如果我们用编程,可以想象用一个足够大的数组将走的所有步骤都保存在起来,记录当前的下标,每次悔棋还原,就将上标前移读取上一次的状态。面向过程我想在座的各位都是神仙选手,所有我们不谈,直接上备忘录模式

看下uml图:
在这里插入图片描述
这个模式由三部分组成:

  1. Originator(发起人):负责创建一个备忘录memeto,用于记录当前时刻的内部状态,并可以使用备忘录恢复内部状态。
  2. Memeto(备忘录):负责存储Originator对象的内部状态,并且防止Originator以外的对象访问备忘录。备忘录有两个接口,CreatMemeto只能看到备忘录的窄接口,他只能将备忘录转递给其他对象。Originator能看到宽接口,允许它访问返回先前状态所需的数据。
  3. CreateMemeto(管理者):负责保存好备忘录Memeto,不能对备忘录的内容进行操作或者检查,可以通过这个接口添加新的内容。

具体实现(c++)

建议copy到本地,跑一跑。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<list>
#include<string>
using namespace std;
class Memeto{
	private:
		int x;
		int y;
		string label;
	public:
		Memeto(){}
		Memeto(int x,int y,string label):x(x),y(y),label(label){};
		int getx(){	return this->x;}
		int gety(){	return this->y;}
		string getlabel(){	return this->label;}		
};
class Originator{
	private:
		int x;
		int y;
		string label;
	public:
		Originator(){}
		Originator(int x,int y,string label):x(x),y(y),label(label){};
		Memeto* save(){
			return new Memeto(this->x,this->y,this->label);
		}
		void restore(Memeto* memeto){
			this->x = memeto->getx();
			this->y = memeto->gety();
			this->label = memeto->getlabel();
		}
		void setx(int x){this->x = x;}
		void sety(int y){this->y = y;}
		void show(){
			cout<<"当前位置下子"<<": "<<this->label<<"<"<<this->x<<","<<this->y<<">!!!"<<endl;
		}
};
class CreatMemeto{
	private:
		list<Memeto*> memetos;
		list<Memeto*>::iterator it;
		int index;
		int nowindex;
	public:
		void addmemeto(Memeto* memeto){
			memetos.push_back(memeto);
			index++;
			nowindex++;
		}
		Memeto* getmemeto(int i){
			int j=0;
			for(it=memetos.begin();it!=memetos.end();it++){
				j++;
				if(j==i){
					return *it;
				}
			}
		}
		void play(Originator* Or){
			addmemeto(Or->save());
			Or->show();
		}
		void regret(Originator* Or){
			if(nowindex<=1){
				cout<<"已经没有步数,无法悔棋"<<endl;
			}
			else{
				cout<<"悔棋"<<endl;
				nowindex--;
				Or->restore(getmemeto(nowindex));
				Or->show();	
			}
		}
		void revokeregret(Originator* Or){
			cout<<"撤销悔棋"<<endl;
			nowindex++;
			if(nowindex > index){
				cout<<"撤销悔棋失败"<<endl;
			}
			else{
				Or->restore(getmemeto(nowindex));
				Or->show();	
			}
			
		}
};
int main(){
	CreatMemeto *Memetos = new CreatMemeto();
	Originator* temp = new Originator(1,1,"黑子");
	Memetos->play(temp);
	temp->setx(2);
	Memetos->play(temp);
	temp->sety(2);
	Memetos->play(temp);
	Memetos->regret(temp);
	Memetos->revokeregret(temp);
	Memetos->regret(temp);
	Memetos->revokeregret(temp);
	Memetos->regret(temp);
	Memetos->regret(temp);
	Memetos->regret(temp);
	Memetos->regret(temp);
	Memetos->revokeregret(temp);
	Memetos->revokeregret(temp);
	Memetos->revokeregret(temp);
}
//运行结果 
/*
当前位置下子: 黑子<1,1>!!!
当前位置下子: 黑子<2,1>!!!
当前位置下子: 黑子<2,2>!!!
悔棋
当前位置下子: 黑子<2,1>!!!
撤销悔棋
当前位置下子: 黑子<2,2>!!!
悔棋
当前位置下子: 黑子<2,1>!!!
撤销悔棋
当前位置下子: 黑子<2,2>!!!
悔棋
当前位置下子: 黑子<2,1>!!!
悔棋
当前位置下子: 黑子<1,1>!!!
已经没有步数,无法悔棋
已经没有步数,无法悔棋
撤销悔棋
当前位置下子: 黑子<2,1>!!!
撤销悔棋
当前位置下子: 黑子<2,2>!!!
撤销悔棋
撤销悔棋失败
*/



特点

优点
Memeto模式比较适用于功能比较复杂的,但需要维护或者记录属性的类,或者需要保存的属性只是众多属性中的一部分时,Originator可以根据保存的Memeto信息还原到前一状态。备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。
缺点:开局一把刀,剩下。。。。。开局我们说,可以用一个足够大的数组保存我们之前操作的状态,足够大足够大,到底多大。不知道,反正就很费存储空间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值