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

备忘录模式(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

posted @ 2019-10-10 17:20  酷学大叔  阅读(355)  评论(0编辑  收藏  举报