• 备忘录模式


    1.概述

      备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)

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

      备忘录模式的用意是在不破坏封装性的条件下,将对象的状态存储起来,从而在未来合适的时候将对象的状态恢复到从前(某个检查点)。

    2.角色

      1)Originator(发起人):负责创建一个含有当前的内部状态备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。

      2)Memento(备忘录):负责存储将发起人对象的内部状态,除了创建它的发起人之外其他对象都不能够访问它。

      备忘录有两个等效的接口:

      窄接口(narrow interface):负责人对象看到的是备忘录的窄接口,这个窄接口只允许它把备忘录对象传给其他的对象;

      宽接口(wide interface):发起人对象可以看到一个宽接口,这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。

      3)Caretaker(管理者): 对备忘录进行管理,保存和提供备忘录。

    3.优缺点

    优点

      1)提供一种可以恢复状态的机制。可以使用户比较方便地回到某个历史状态。

      2) 保持封装边界。使用备忘录可以避免暴露一些只应由原发器管理却又必须存储在原发器之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽起来,从而保持了封装边界

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

      1) 备忘录模式会占用较多的内存,消耗资源。如果原发器在生成备忘录时必须拷贝并存储大量的信息,或者客户非常频繁地创建备忘录和恢复原发器状态,可能会导致非常大的开销。
      2) 维护备忘录的潜在代价。管理器负责删除它所维护的备忘录。然而,管理器不知道备忘录中有多少个状态。因此当存储备忘录时,一个本来很小的管理器,可能会产生大量的存储开销。

    4.适用性

      1)需要保存一个对象在某一个时刻的状态或部分状态。
      2)如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

    5.代码

      1)例一:《大话设计模式C++版》

     1 #include "stdafx.h"
     2 #include <iostream>
     3 #include <string>
     4 using namespace std;
     5 
     6 class Memo;
     7 
     8 //发起人类
     9 //1、创建一个含有当前的内部状态的备忘录对象。 
    10 //2、使用备忘录对象存储其内部状态。 
    11 class Originator
    12 {
    13 public:
    14   string state;
    15   Memo* CreateMemo();
    16   void SetMemo(Memo* memo);
    17   void Show()
    18   {
    19     cout<<"状态:"<<state<<endl;
    20   }
    21 };
    22 //备忘录类
    23 class Memo
    24 {
    25 public:
    26   string state;
    27   Memo(string strState)
    28   {
    29     state= strState;
    30   }
    31 };
    32 
    33 Memo* Originator::CreateMemo()
    34 {
    35    return new Memo(state);
    36 }
    37 
    38 void Originator::SetMemo(Memo* memo)
    39 {
    40   state = memo->state;
    41 }
    42 
    43 //管理者类
    44 //1、负责保存备忘录对象 
    45 //2、不检查备忘录对象的内容。
    46 class Caretaker
    47 {
    48 public:
    49   Memo* memo;
    50 };
    51 
    52 //客户端:
    53 int main()
    54 {
    55   // 创建一个原发器
    56   Originator* on=new Originator();
    57   on->state = "on";
    58   on->Show();
    59 
    60   // 创建一个备忘录存放这个原发器的状态
    61   Caretaker* c= new Caretaker();
    62   c->memo = on->CreateMemo();
    63 
    64   // 更改原发器的状态
    65   on->state = "off";
    66   on->Show();
    67 
    68   // 通过备忘录把原发器的状态还原到之前的状态
    69   on->SetMemo(c->memo);
    70   on->Show();
    71   
    72   system("pause");
    73   return 0;
    74 }

      2)例二:

      http://blog.csdn.net/lcl_data/article/details/9745019

     1 #include "stdafx.h"
     2 #include <iostream>
     3 #include <string>
     4 using namespace std;
     5 
     6 class Memento {
     7 private:
     8   string state;
     9 
    10 public:
    11   Memento()
    12   {
    13     state = "";
    14   }
    15   Memento(string state){
    16     this->state = state;
    17   }
    18   string getState() {
    19     return state;
    20   }
    21   void setState(string state) {
    22     this->state = state;
    23   }
    24 };
    25 
    26 class Originator {
    27 private :
    28   string state;
    29 
    30 public:
    31   Originator()
    32   {
    33     state = "";
    34   }
    35 
    36   string getState() {
    37     return state;
    38   }
    39   void setState(string state) {
    40     this->state = state;
    41   }
    42   Memento createMemento(){
    43     return Memento(this->state);
    44   }
    45     void restoreMemento(Memento memento){
    46     this->setState(memento.getState());
    47   }
    48 };
    49 
    50 class Caretaker {
    51 private :
    52   Memento memento;
    53 public :
    54   Memento getMemento(){
    55     return memento;
    56   }
    57   void setMemento(Memento memento){
    58     this->memento = memento;
    59   }
    60 };
    61 
    62 int main (int argc, char *argv[]) 
    63 {
    64   Originator originator;
    65   originator.setState("状态");
    66   cout<<"初始状态:"<<originator.getState()<<endl;
    67   Caretaker caretaker;
    68   caretaker.setMemento(originator.createMemento());
    69   originator.setState("状态");
    70   cout<<"改变后状态:"<<originator.getState()<<endl;
    71   originator.restoreMemento(caretaker.getMemento());
    72   cout<<"恢复后状态:"<<originator.getState()<<endl;
    73 
    74   system("pause");
    75   return 0;
    76 }

  • 相关阅读:
    leetcode Ch2-Dynamic Programming I
    leetcode Ch3-DFS & Backtracking II
    关于尾递归
    leetcode BFS
    linux各文件夹的作用
    auto_ptr与shared_ptr ZZ
    漏洞分析中常用的堆调试支持
    【读书笔记】Android平台的漏洞挖掘和分析
    关于Fuzz——peach的学习
    如何验证一个地址可否使用—— MmIsAddressValid函数分析
  • 原文地址:https://www.cnblogs.com/SnailProgramer/p/4283152.html
Copyright © 2020-2023  润新知