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