欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-11 15:55:20
备忘录模式(Memento): 后悔药来啦!!!备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便在需要时能将该对象恢复到原先保存的状态。 备忘录模式的角色: 1)发起人(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能 ......

备忘录模式(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)提供一个可回滚的操作。

参考: