在GOF的《设计模式:可复用面向对象软件的基础》一书中对备忘录模式是这样说的:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

类图和实例:

简单的模式实例:
#include <iostream>
#include <string>
using namespace std;
class Memento {
private:
    string state; public:
    Memento()
    {
        state = "";
    }
    Memento(string state){
        this->state = state;
    }
    string getState() {
        return state;
    }
    void setState(string state) {
        this->state = state;
    }
}; class Originator {
private :
    string state; public:
    Originator()
    {
        state = "";
    }     string getState() {
        return state;
    }
    void setState(string state) {
        this->state = state;
    }
    Memento createMemento(){
        return Memento(this->state);
    }
    void restoreMemento(Memento memento){
        this->setState(memento.getState());
    }
}; class Caretaker {
private :
    Memento memento;
public :
    Memento getMemento(){
        return memento;
    }
    void setMemento(Memento memento){
        this->memento = memento;
    }
};
int main (int argc, char *argv[])   
{
    Originator originator;
    originator.setState("状态1");
    cout<<"初始状态:"<<originator.getState()<<endl;
    Caretaker caretaker;
    caretaker.setMemento(originator.createMemento());
    originator.setState("状态2");
    cout<<"改变后状态:"<<originator.getState()<<endl;
    originator.restoreMemento(caretaker.getMemento());
    cout<<"恢复后状态:"<<originator.getState()<<endl;
}

UML类图

Memento:备忘录存储原发器对象的内部状态。原发器根据需要决定备忘录存储原发器的哪些内部状态;防止原发器以外的其他对象访问备忘录。备忘录实际上有两个接口,管理者只能看到备忘录的窄接口————它只能将备忘录传递给其他对象。相反,原发器能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。理想的情况是只允许生成备忘录的那个原发器访问本备忘录的内部状态;
Originator:原发器创建一个备忘录,用以记录当前时刻它的内部状态;我们使用备忘录恢复内部状态;
Caretaker:负责保存好备忘录;但是,不能对备忘录的内容进行操作或检查。

备忘录模式是按照以下方式进行协作的:
管理器向原发器请求一个备忘录,保留一段时间后,将其送回给原发器;而有的时候管理者不会将备忘录返回给原发器,因为原发器可能根本不需要退到先前的状态。备忘录是被动的,只有创建备忘录的原发器会对它的状态进行赋值和检索,如下面的时序图:

#include <iostream>
using namespace std; struct State
{
wchar_t wcsState[];
}; class Memento
{
public:
Memento(State *pState) : m_pState(pState){} State *GetState() { return m_pState; } private:
friend class Originator; State *m_pState;
}; class Originator
{
public:
Originator() : m_pState(NULL) {}
~Originator()
{
// Delete the storage of the state
if (m_pState)
{
delete m_pState;
m_pState = NULL;
}
} void SetMemento(Memento *pMemento);
Memento *CreateMemento(); void SetValue(wchar_t *value)
{
memset(wcsValue, , * sizeof(wchar_t));
wcscpy_s(wcsValue, , value);
} void PrintState() { wcout<<wcsValue<<endl; } private:
State *m_pState; // To store the object's state wchar_t wcsValue[]; // This is the object's real data
}; Memento *Originator::CreateMemento()
{
m_pState = new State;
if (m_pState == NULL)
{
return NULL;
} Memento *pMemento = new Memento(m_pState); wcscpy_s(m_pState->wcsState, , wcsValue); // Backup the value
return pMemento;
} void Originator::SetMemento(Memento *pMemento)
{
m_pState = pMemento->GetState(); // Recovery the data
memset(wcsValue, , * sizeof(wchar_t));
wcscpy_s(wcsValue, , m_pState->wcsState);
} // Manager the Memento
class Caretaker
{
public:
Memento *GetMemento() { return m_pMemento; }
void SetMemnto(Memento *pMemento)
{
// Free the previous Memento
if (m_pMemento)
{
delete m_pMemento;
m_pMemento = NULL;
} // Set the new Memento
m_pMemento = pMemento;
} private:
Memento *m_pMemento;
}; int main()
{
Originator *pOriginator = new Originator();
pOriginator->SetValue(L"On");
pOriginator->PrintState(); // Now I backup the state
Caretaker *pCaretaker = new Caretaker();
pCaretaker->SetMemnto(pOriginator->CreateMemento()); // Set the new state
pOriginator->SetValue(L"Off");
pOriginator->PrintState(); // Recovery to the old state
pOriginator->SetMemento(pCaretaker->GetMemento());
pOriginator->PrintState(); if (pCaretaker)
{
delete pCaretaker;
} if (pOriginator)
{
delete pOriginator;
} return ;
}

适用性:

适用于功能比较复杂的,但需要记录或维护属性历史的类;或者需要保存的属性只是众多属性中的一小部分时Originator可以根据保存的Memo还原到前一状态。

优缺点:

优点:

1)当发起人角色的状态有改变时,有可能是个错误的改变,我们使用备忘录模式就可以把这个错误改变还原。

2)备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。

缺点:

1)如果备份的对象存在大量的信息或者创建、恢复操作非常频繁,则可能造成很大的性能开销。

 
 

[设计模式] 18 备忘录模式Memento Pattern的更多相关文章

  1. 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern)

    原文:乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) 作者:webabc ...

  2. 二十四种设计模式:备忘录模式(Memento Pattern)

    备忘录模式(Memento Pattern) 介绍在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到保存的状态. 示例有一个Message实体类,某 ...

  3. 备忘录模式-Memento Pattern(Java实现)

    备忘录模式-Memento Pattern Memento备忘录设计模式是一个保存另外一个对象内部状态拷贝的对象,这样以后就可以将该对象恢复到以前保存的状态. 本文中的场景: 有一款游戏可以随时存档, ...

  4. 设计模式之备忘录模式(Memento)

    备忘录模式(Memento) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. Originator(发起人):负责创建一个备忘录 ...

  5. 【设计模式】—— 备忘录模式Memento

    前言:[模式总览]——————————by xingoo 模式意图 这个模式主要是想通过一个对象来记录对象的某种状态,这样有利于在其他需要的场合进行恢复. 该模式还有跟多可以扩展的地方,比如可以记录多 ...

  6. 23.备忘录模式(Memento Pattern)

    using System; using System.Collections.Generic; namespace ConsoleApplication6 { /// <summary> ...

  7. 备忘录模式-Memento Pattern

    1.主要优点 备忘录模式的主要优点如下: (1)它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原. (2) ...

  8. 设计模式 笔记 备忘录模式 Memento

    //---------------------------15/04/27---------------------------- //Memento 备忘录模式----对象行为型模式 /* 1:意图 ...

  9. 用最简单的例子理解备忘录模式(Memento Pattern)

    简单来说,备忘录模式就是支持回退操作.假设让一个Notepad支持回退操作,如何实现呢? 首先需要一个备忘录类. public class Memento { private string _msg; ...

随机推荐

  1. 理解C#系列 / 核心C# / 变量

    变量 变量? 变量是对一个东西指定一个名称,变量的功能和人的名字差不多,提到名字就知道指的是什么. 变量类型? 变量类型说明了变量的类型,声明变量是一个整数,还是小数,还是字符,或是图像,或是人类,或 ...

  2. OC3-xml文件解析

    <?xml version="1.0"?> <xml_api_reply version="1"> <cities> < ...

  3. Spring IOC整理

    示例展示 Spring的一大特点是利用配置的xml文件实现依赖注入. 所谓依赖注入是指把一个业务对象注入另一个业务对象,从而达到对象间的松耦合.(注意是业务对象哦!)依赖注入讲的通俗一点,就是让一个对 ...

  4. 南阳理工ACM——106背包问题

    描述: 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w<=10):如果给你一个背包它能容纳的重量为m(10<=m<=20),你 ...

  5. 正确编写Designated Initializer的几个原则

    Designated Initializer(指定初始化器)在Objective-C里面是很重要的概念,但是在日常开发中我们往往会忽视它的重要性,以至于我们写出的代码具有潜藏的Bug,且不易发现.保证 ...

  6. 自定义可判断选项是否正确listbox

    截图如下:        1.实现Converter  获取到listbox,并得到listitem在listbox中的index public class ItemContainerToZIndex ...

  7. exynos 4412 电源管理芯片PMIC 的配置及使用方法

    /** ****************************************************************************** * @author    Maox ...

  8. shell脚本初识

    #!/bin/bash(linux脚本环境的声明即解释器,该解释器为bash,位于根目录下的bin目录下) 变量的定义与赋值: 格式:变量名=变量值(无需声明变量类型) 变量的引用: 格式:$变量名 ...

  9. 【Qt】Qt之自定义界面(右下角冒泡)【转】

    简述 网页右下角上经常会出现一些提示性的信息,桌面软件中也比较常见,类似360新闻.QQ消息提示一样! 这种功能用动画实现起来很简单,这节我们暂时使用定时器来实现,后面章节会对动画框架进行详细讲解. ...

  10. laravel--has方法--查看关联关系

    has()方法可以用来查询是否有关联关系的一个东西,一般其他的has方法 就是判断这个里面有没有值 $packageOrders = Company::has('packages')->get( ...