C++设计模式_19_Memento 备忘录(理解,目前多使用序列化方案来实现)

Memento 备忘录模式也属于“状态变化”模式,它是一个小模式,在今天来看有些过时,当今已经很少使用当前模式实现需求,思想却不变(信息隐藏),目前多使用序列化方案来实现。本系列所介绍的模式,有一些随着时代的变化,有一些过时。

文章目录

  • 1. 动机( Motivation)
  • 2. 模式定义
  • 3. Memento 备忘录模式代码实现
  • 4. 结构( Structure )
  • 5. 要点总结
  • 6. 其他参考

1. 动机( Motivation)

  • 在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。

Memento 备忘录模式主要解决维持封装性的前提下,怎么样去实现对象的状态

  • 如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性

2. 模式定义

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

----《设计模式》GoF

3. Memento 备忘录模式代码实现

假设下面的对象是需要保存状态的对象,他的状态可能有很多,此处只释义性的放了字符串state,省略号代表还有其他很多的状态。

class Originator
{
    string state;
    //....
public:
    Originator() {}
    Memento createMomento() {
        Memento m(state);
        return m;
    }
    void setMomento(const Memento & m) {
        state = m.getState();
    }
};

这个对象有一个需求,我们想在某些点把它的状态拍一些内存快照存起来,我们设计了另外一个对象,他的状态内部表示是和Originator对应的为state,当然在现实实现中,这个状态有可能只摘取Originator中某些有效的状态,在实现上也不一定一模一样,Originator中可能是一些字段,在Memento中可能是一个内存流、一个经过base 64编码之后的字符串。又提供了一定的接口供Originator访问

class Memento
{
    string state;
    //..
public:
    Memento(const string & s) : state(s) {}
    string getState() const { return state; }
    void setState(const string & s) { state = s; }
};

代码分析:

Originator中的利用以下代码将现有的状态塞进来,创建一个Momento,Memento m(state);在不同平台的实现可能相当复杂,往往使用编码器访问转成其他的存储模式-内存流、字符串,最后再返回对象。以下的代码就相当于当前内存状态拍照

    Memento createMomento() {
        Memento m(state);
        return m;
    }

使用:orginator称为原发器,Memento mem = orginator.createMomento();创建出一个备忘录并存储到备忘录的对象中(稳定,不动的),后在程序运行时更改原发器的状态//... 改变orginator状态,在某一点需要把之前那个点存储的对象的状态恢复,orginator.setMomento(memento);中orginator点setMomento,改变回原状态,state = m.getState();是非常示意性的代码,具体在实现过程中可能会比较复杂。

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

整体代码如下:

class Memento
{
    string state;
    //..
public:
    Memento(const string & s) : state(s) {}
    string getState() const { return state; }
    void setState(const string & s) { state = s; }
};



class Originator
{
    string state;
    //....
public:
    Originator() {}
    Memento createMomento() {
        Memento m(state);
        return m;
    }
    void setMomento(const Memento & m) {
        state = m.getState();
    }
};



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

Memento 备忘录理解起来比较简单,但是到不同平台上,具体实现会不同。

4. 结构( Structure )

C++设计模式_19_Memento 备忘录(理解,目前多使用序列化方案来实现)_第1张图片

5. 要点总结

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

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

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

6. 其他参考

C++设计模式——备忘录模式

你可能感兴趣的:(#,C++设计模式,c++,设计模式)