一:概念

用于保存对象的内部状态,并在需要的时候(undo/rollback)回复对象以前的状态

二:应用场景

如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。

)一个类需要保存它的对象的状态(相当于Originator角色);
)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色);
)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存;
)undo或rollback操作时,通过Caretacker保存的Memento恢复Originator对象的状态。

三:动机

在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需求,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其它对象得到对象的状态,便会暴露对象的实现细节。
如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。

四:模式定义

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

                                                                    ——《设计模式》GoF

五:代码讲解

(一)需要保存状态的对象

class Originator
{
string state;
//....多个内部状态
public:
Originator() {}
Memento createMomento() {
Memento m(state);  //在某个点时对状态(有可能需要编码序列化等操作)进行快照保存
return m;
}
void setMomento(const Memento & m) {
state = m.getState();  
}
};

补充:

函数的局部对象在当前函数被调用的时候创建,存储在栈区,在函数结束以后就会被释放,如果存在返回值,那么当前对象也会被释放,只不过在被释放前
做了一次拷贝,拷贝到接受该返回值的另外一个对象上面,所以函数的入参和返回值其实都进行的是拷贝操作,新的对象被赋值,旧的的对象被回收

(二)外部保存对象状态的类

class Memento
{
string state;  //保存方式多样,序列化,内存流等方式
//..和上面状态对应,存储其中有效的状态(不一定是一模一样)
public:
Memento(const string & s) : state(s) {}
string getState() const { return state; }
void setState(const string & s) { state = s; }
};

(三)使用

int main()
{
Originator orginator;  //原发器 //捕获对象状态,存储到备忘录
Memento mem = orginator.createMomento(); //... 改变orginator状态 //从备忘录中恢复
orginator.setMomento(memento); }

六:类图(结构)

七:要点总结

(一)备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器的状态。

(二)Memento模式的核心是信息隐藏,即Originator需要向外接隐藏信息,保持其封装性。但同时又需要将其状态保持到外界(Memento)

(三)由于现代语言运行时(如C#、java等)都具有相当的对象序列化支持,因此往往采用效率较高、又较容易正确实现的序列化方案来实现Memento模式。

八:案例演示

(一)备忘录实现

//备忘录
class MememTo
{
private:
string m_name;
int m_age;
public:
MememTo(string name,int age)  //构造数据来源于我们想要保存的信息
{
this->m_name = name;
this->m_age = age;
} void setName(string name)
{
this->m_name = name;
} void setAge(int age)
{
this->m_age = age;
} string getName()
{
return m_name;
} int getAge()
{
return m_age;
}
};

(二)构造原发器

//原发器
class Person
{
private:
string m_name;
int m_age;
public:
Person(string name,int age)
{
this->m_age = age;
this->m_name = name;
} void setName(string name)
{
this->m_name = name;
} void setAge(int age)
{
this->m_age = age;
} string getName()
{
return m_name;
} int getAge()
{
return m_age;
} void printInfo()
{
cout << m_name << " is " << m_age << endl;
}
public:
//创建备份
MememTo* createMememTo()
{
return new MememTo(m_name, m_age);
} //恢复备份
void SetMememTo(MememTo* memto)
{
m_age = memto->getAge();
m_name = memto->
getName();
}

};

(三)实现管理者

//管理者,写在外面调用有点多余,直接将main作为管理者
class CareTaker
{
private:
MememTo* m_memto;
public:
CareTaker(MememTo* mem)
{
this->m_memto = mem;
} MememTo* getMememTo()
{
return m_memto;
} void setMememTo(MememTo* mem)
{
this->m_memto = mem;
}
};
void main()
{
Person* p = new Person("zhangsan", );
p->printInfo();
//创建备份
MememTo* membak = p->createMememTo();
p->createMememTo(); p->setAge();
p->setName("lisi");
p->printInfo(); //恢复信息
p->SetMememTo(membak);
p->printInfo(); system("pause");
return;
}

设计模式---状态变化模式之备忘录模式(Memento)的更多相关文章

  1. Java设计模式(15)备忘录模式(Memento模式)

    Memento定义:memento是一个保存另外一个对象内部状态拷贝的对象,这样以后就可以将该对象恢复到原先保存的状态. Memento模式相对也比较好理解,我们看下列代码: public class ...

  2. 【设计模式 - 18】之备忘录模式(Memento)

    1      模式简介 备忘录模式的定义: 备忘录模式保存一个对象的某个状态,以便在适当的时候恢复对象,用作"后悔药",即取消上次操作或返回到以前的某个版本. 备忘录模式的应用实例 ...

  3. Java进阶篇设计模式之十二 ---- 备忘录模式和状态模式

    前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...

  4. Java设计模式之十二 ---- 备忘录模式和状态模式

    前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...

  5. 设计模式20---设计模式之备忘录模式(Memento)(行为型)

    1.讲解备忘录模式 备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Token模式,是GoF的23种设计模式之一,属于行为模式. 1.1定义 在不破坏封 ...

  6. 设计模式的征途—20.备忘录(Memento)模式

    相信每个人都有后悔的时候,但是人生并无后悔药,有些错误一旦发生就无法再挽回,有些事一旦错过就不会再重来,有些话一旦说出口也就不可能再收回,这就是人生.为了不让自己后悔,我们总是需要三思而后行.这里我们 ...

  7. Java设计模式(21)——行为模式之备忘录模式(Memento)

    一.概述 概念 UML简图 角色 根据下图得到角色 备忘录角色(Memento).发起人角色(Originator).负责人角色(Caretaker) 二.实践 使用白箱实现,给出角色的代码: 发起人 ...

  8. Head First 设计模式系列之二----备忘录模式(java版)

    申明:这几天无意中关注到备忘录模式,比较陌生回家一番参考书,只在附录里记录了该模式.后来在园子里有发现了有专门写设计模式的博客,并且写的也得牛逼.附上链接 http://www.cnblogs.com ...

  9. 行为型模式(十) 备忘录模式(Memento)

    一.动机(Motivate) 我们看上图,一个对象肯定会有很多状态,这些状态肯定会相互转变而促进对象的发展,如果要想在某一时刻把当前对象回复到以前某一时刻的状态,这个情况用"备忘录模式&qu ...

随机推荐

  1. 【BZOJ3992】【SDOI2015】序列统计 原根 NTT

    题目大意 有一个集合\(s\),里面的每个数都\(\geq0\)且\(<m\). 问有多少个长度为\(n\)的数列满足这个数列所有数的乘积模\(m\)为\(x\).答案模\(1004535809 ...

  2. hdu 2159 FATE (二维完全背包)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 思路: dp[j][k] 代表消耗耐久度j,干掉k个敌人获得的经验值. 状态转移方程为: dp[j] ...

  3. Java 元编程及其应用

    Java 元编程及其应用 首先,我们且不说元编程是什么,他能做什么.我们先来谈谈生产力. 同样是实现一个投票系统,一个是python程序员,基于django-framework,用了半小时就搭建了一个 ...

  4. 允许外网访问MySQL

    1:设置mysql的配置文件     /etc/mysql/my.cnf     找到 bind-address  =127.0.0.1  将其注释掉://作用是使得不再只允许本地访问:  重启mys ...

  5. 【BZOJ1188】分裂游戏(博弈论)

    [BZOJ1188]分裂游戏(博弈论) 题面 BZOJ 洛谷 题解 这道题目比较神仙. 首先观察结束状态,即\(P\)状态,此时必定是所有的豆子都在最后一个瓶子中. 发现每次的转移一定是拿出一棵豆子, ...

  6. extern C小结

    名词解释 1.extern extern翻译为外部的,用在变量或函数之前,使其可见范围拓宽,这就是为啥叫extern吧.那它是用来干嘛的呢?当用在变量或函数之前,提示编译器到其他模块寻找其定义. 举个 ...

  7. CF1139E Maximize Mex(二分图匹配,匈牙利算法)

    好题.不过之前做过的[SCOI2010]连续攻击游戏跟这题一个套路,我怎么没想到…… 题目链接:CF原网 洛谷 题目大意:在一个学校有 $n$ 个学生和 $m$ 个社团,每个学生有一个非负整数能力值 ...

  8. hdu 1978 How many ways(记忆化搜索)

    这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下:1.机器人一开始在棋盘的起始点并有起始点所标有的能量.2.机器人只能向右或者向下走,并 ...

  9. 树状数组入门 hdu1541 Stars

    树状数组 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次 ...

  10. NowCoder--牛客练习赛30 C_小K的疑惑

    题目链接 :牛客练习赛30 C_小K的疑惑 i j k 可以相同 而且 距离%2 只有 0 1两种情况 我们考虑 因为要 d(i j)=d(i k)=d(j k) 所以我们只能找 要么三个点 任意两个 ...