在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. 下拉框的选择跳转事件(jqure)

    <select id="coupontype"> <option value="@CouponType.全部" href="@Url ...

  2. 一些常用的字符串hash函数

    unsigned int RSHash(const std::string& str) { unsigned int b = 378551; unsigned int a = 63689; u ...

  3. 各个公司的来源/The etymology of company

    1.List of Company Etymology 下面的维基百科词条是比较有名的一些公司的名称的来源 List of company name etymologies 2.Atmel : adv ...

  4. Ubuntu14.04 安装 PHP cURL

    今天遇到 Fatal error: Call to undefined function curl_init() in /xxx/xxxx/www/application/library/Ku/Htt ...

  5. ORACLE 基础知识积累

    创建ORACLE 数据库,首先用Sys账号角色为dba进入数据库然后,然后根据创建数据库的表空间,然后创建角色,创建完角色后将表空间的权限授予角色. SQL语句如下: create temporary ...

  6. NOSQL之【redis的安全策略】

    原文:http://redis.io/topics/security 1.Redis的安全模式 可信环境下的可信用户才可访问redis.这意味着,将redis服务器直接暴露在Internet或者不可信 ...

  7. referenceerror wx is not defined 微信JsSdk开发

    如果你和我一样遇到了“referenceerror wx is not defined”错误,很有可能是jweixin-1.0.0.js与你其它某js冲突. 解决办法: <script type ...

  8. [Solved] install Gentoo in VBox: network interface eth0 does not exist

    ERROR:interface eth0 does not exist; ensure that you have loaded the correct kernel moudle for your ...

  9. BI的核心价值[转]

    BI的核心价值是辅助决策,从一个洁净的数据源中自动提取有价值的数据进行分析,从而成为重要商业决定的决策基础.但在国内,洁净的数据源不易得到,很多情况下都需要进行数据清洗,所以BI的应用受到很大程度的抑 ...

  10. php中调用用户自定义函数的方法:call_user_func,call_user_func_array

    看UCenter的时候有一个函数call_user_func,百思不得其解,因为我以为是自己定义的函数,结果到处都找不到,后来百度了一下才知道call_user_func是内置函数,该函数允许用户调用 ...