• 设计模式-行为型-备忘录模式


    备忘录模式(Memento):

      后悔药来啦!!!备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便在需要时能将该对象恢复到原先保存的状态。

    备忘录模式的角色:

      

      1)发起人(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。

      2)备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。

      3)管理者(CareTaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

      根据上述UML图实现代码: 

     1 internal class Program
     2 {
     3     private static void Main(string[] args)
     4     {
     5         Originator o = new Originator();
     6         o.State = "On";
     7 
     8         Caretaker c = new Caretaker();
     9         c.Memento = o.CreateMemento();
    10 
    11         o.State = "Off";
    12         o.SetMemento(c.Memento);
    13     }
    14 }
    15 
    16 /// <summary>
    17 /// 备忘录
    18 /// </summary>
    19 public class Memento
    20 {
    21     private string _state;
    22 
    23     public Memento(string state)
    24     {
    25         this._state = state;
    26     }
    27 
    28     public string State
    29     {
    30         get { return _state; }
    31     }
    32 }
    33 
    34 /// <summary>
    35 /// 发起人
    36 /// </summary>
    37 public class Originator
    38 {
    39     private string _state;
    40 
    41     public string State
    42     {
    43         get
    44         {
    45             return _state;
    46         }
    47         set
    48         {
    49             _state = value;
    50             Console.WriteLine("State = " + _state);
    51         }
    52     }
    53 
    54     public Memento CreateMemento()
    55     {
    56         return (new Memento(_state));
    57     }
    58 
    59     public void SetMemento(Memento memento)
    60     {
    61         Console.WriteLine("Restoring state...");
    62         State = memento.State;
    63     }
    64 }
    65 
    66 /// <summary>
    67 /// 管理者
    68 /// </summary>
    69 public class Caretaker
    70 {
    71     private Memento _memento;
    72 
    73     public Memento Memento
    74     {
    75         get
    76         {
    77             return _memento;
    78         }
    79         set
    80         {
    81             _memento = value;
    82         }
    83     }
    84 }

      现实生活中,我们往往会进行文档的备份或者SVN,git的快照。

      1 internal class Program
      2 {
      3     private static void Main(string[] args)
      4     {
      5         List<Document> docs = new List<Document>()
      6         {
      7             new Document{ Name="水浒传", Content="水浒传123131231"  },
      8             new Document{ Name="三国演义", Content="三国演义111111"  }
      9         };
     10 
     11         Originator originator = new Originator(docs);
     12         Caretaker caretaker = new Caretaker();
     13         DateTimeOffset time1 = new DateTimeOffset(DateTime.Now);
     14         caretaker.MementoDic.Add(time1, originator.CreateMemento());
     15         originator.GetShow();
     16         Console.WriteLine("====================================");
     17         Console.WriteLine("修改内容");
     18         docs[0].Content = "新水浒,搞笑ing";
     19         DateTimeOffset time2 = new DateTimeOffset(DateTime.Now);
     20         caretaker.MementoDic.Add(time2, originator.CreateMemento());
     21         originator.GetShow();
     22         Console.WriteLine("====================================");
     23         Console.WriteLine("回滚到第一阶段");
     24         originator.SetMemento(caretaker.MementoDic[time1]);
     25         originator.GetShow();
     26         Console.WriteLine("回滚到第二阶段");
     27         originator.SetMemento(caretaker.MementoDic[time2]);
     28         originator.GetShow();
     29     }
     30 }
     31 
     32 /// <summary>
     33 /// 文件
     34 /// </summary>
     35 public class Document
     36 {
     37     public string Name { get; set; }
     38     public string Content { get; set; }
     39 }
     40 
     41 /// <summary>
     42 /// 备忘录
     43 /// </summary>
     44 public class Memento
     45 {
     46     public List<Document> fileBack;
     47 
     48     public Memento(List<Document> docs)
     49     {
     50         this.fileBack = docs;
     51     }
     52 }
     53 
     54 /// <summary>
     55 /// 发起人
     56 /// </summary>
     57 public class Originator
     58 {
     59     //内部状态
     60     public List<Document> docs;
     61 
     62     public Originator(List<Document> docs)
     63     {
     64         this.docs = docs;
     65     }
     66 
     67     public Memento CreateMemento()
     68     {
     69         // 深拷贝传递对象
     70         var str = JsonConvert.SerializeObject(this.docs);
     71         return new Memento(JsonConvert.DeserializeObject<List<Document>>(str));
     72     }
     73 
     74     public void SetMemento(Memento memento)
     75     {
     76         Console.WriteLine("Restoring state...");
     77         docs = memento.fileBack;
     78     }
     79 
     80     /// <summary>
     81     /// 显示信息
     82     /// </summary>
     83     public void GetShow()
     84     {
     85         foreach (var doc in docs)
     86         {
     87             Console.WriteLine($"文件名:{doc.Name},内容:{doc.Content}");
     88         }
     89     }
     90 }
     91 
     92 /// <summary>
     93 /// 管理者
     94 /// </summary>
     95 public class Caretaker
     96 {
     97     // 使用多个备忘录来存储多个备份点
     98     public Dictionary<DateTimeOffset, Memento> MementoDic { get; set; }
     99 
    100     public Caretaker()
    101     {
    102         MementoDic = new Dictionary<DateTimeOffset, Memento>();
    103     }
    104 }

    备忘录模式的优缺点:

      优点:

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

        2)实现了信息的封装,使得用户不需要关心状态的保存细节。

      缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

    备忘录模式的应用场景:

      1)需要保存/恢复数据的相关状态场景。

      2)提供一个可回滚的操作。

    参考:https://blog.csdn.net/heyangyi_19940703/article/details/51376570

  • 相关阅读:
    根据基本表结构及其数据生成SQL语句
    (转)一个DbHelper数据操作类
    解决AJAX中使用UpdatePanel后再用Response.Write();等无法弹出对话框问题 3法
    今天看到的一些软件工程管理的辅助软件
    编写维护状态的自定义WEB服务器控件
    webBrowser.execWB的完整说明
    [导入]在Web.Config中指定页面的基类
    [导入]一处 ADO.NET Entity Framework 的逻辑BUG
    [导入]在后台代码中引入XAML的方法
    选择排序(java版)
  • 原文地址:https://www.cnblogs.com/az4215/p/11647481.html
Copyright © 2020-2023  润新知