[设计模式] 备忘录模式Memento Pattern

在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[260];
};

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, 0, 260 * sizeof(wchar_t));
          wcscpy_s(wcsValue, 260, value);
     }

     void PrintState() { wcout<<wcsValue<<endl; }

private:
     State *m_pState; // To store the object‘s state

     wchar_t wcsValue[260]; // 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, 260, wcsValue); // Backup the value
     return pMemento;
}

void Originator::SetMemento(Memento *pMemento)
{
     m_pState = pMemento->GetState();

     // Recovery the data
     memset(wcsValue, 0, 260 * sizeof(wchar_t));
     wcscpy_s(wcsValue, 260, 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 0;
}

适用性:

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

优缺点:

优点:

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

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

缺点:

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

时间: 2024-10-05 06:44:35

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

设计模式(行为型)之备忘录模式(Memento Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之中介者模式(Mediator Pattern)>http://blog.csdn.net/yanbober/article/details/45533335 概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无

备忘录模式(Memento Pattern)

备忘录模式(Memento Pattern)用来恢复一个对象的状态到以前的状态. 备忘录模式下属于行为模式的类别. 实现实例 在这个示例中,备忘录模式(Memento Pattern)使用三个操作者类. Memento类中包含要恢复的对象的状态. 创建者在Memento对象中创建和存储状态,Caretaker对象负责从Memento中恢复对象状态.在这个示例中,创建了以下几个类:Memento,Originator和CareTaker. MementoPatternDemo这是一个演示类,它将使

[工作中的设计模式]备忘录模式memento

一.模式解析 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态.备忘录模式常常与命令模式和迭代子模式一同使用. 备忘录模式可以根据客户指令,将相应的对象特有属性进行快照,如果客户要恢复对象,则根据快照提供的特有属性进行还原. 二.模式代码 package memento.patten; /** *备忘录类,同时指定要保存的对象属性

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

简单来说,备忘录模式就是支持回退操作.假设让一个Notepad支持回退操作,如何实现呢? 首先需要一个备忘录类. public class Memento { private string _msg; public Memento(string msg) { _msg = msg; } public string GetText() { return _msg; } } 以上,○ 构造函数在Nodepad每次记录信息的时候调用,Nodepad所记录的信息最终通过该构造函数赋值给了_msg字段.○

C#面向对象设计之——备忘录模式Memento Pattern(二十三)

一.前言 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象回复到原先保存的状态. 二.结构图 三.实例代码 using System; using System.Collections.Generic; using System.Text; namespace 备忘录模式 { class Program { static void Main(string[] args) { Originator o = new Originator()

23.备忘录模式(Memento Pattern)

using System; using System.Collections.Generic; namespace ConsoleApplication6 { /// <summary> /// 从字面意思就可以明白,备忘录模式就是对某个类的状态进行保存下来, /// 等到需要恢复的时候, /// 可以从备忘录中进行恢复.生活中这样的例子经常看到, /// 如备忘电话通讯录,备份操作操作系统,备份数据库等. /// </summary> class Program { static

深入浅出设计模式——备忘录模式(Memento Pattern)

模式动机 为了使软件的使用更加人性化,对于误操作,我们需要提供一种类似“后悔药”的机制,让软件系统可以回到误操作前的状态,因此需要保存用户每一次操作时系统的状态,一旦出现误操作,可以把存储的历史状态取出即可回到之前的状态.现在大多数软件都有撤销(Undo)的功能,快捷键一般都是Ctrl+Z,目的就是为了解决这个后悔的问题. 在应用软件的开发过程中,很多时候我们都需要记录一个对象的内部状态.在具体实现过程中,为了允许用户取消不确定的操作或从错误中恢复过来,需要实现备份点和撤销机制,而要实现这些机制

设计模式之备忘录模式(Memento)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

设计模式入门之备忘录模式Memento

//备忘录模式定义: //在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态. //这样以后就可以将该对象恢复到原先保存的状态 //实例:测试两种方案,两种方案在第一阶段的过程是相同的,第二阶段是不同的 //实例代码 //备忘录对象的窄接口 public interface FlowAMockMemento { //空的,所谓窄接口,即只是一个标识作用,它的持有者不可以调用任何它的方法 } //测试流程类 public class FlowAMock { private