备忘录Memento Pattern模式q.docx
《备忘录Memento Pattern模式q.docx》由会员分享,可在线阅读,更多相关《备忘录Memento Pattern模式q.docx(28页珍藏版)》请在冰豆网上搜索。
备忘录MementoPattern模式q
备忘录(MementoPattern)模式
备忘录模式又叫做快照模式(SnapshotPattern)或Token模式,是对象的行为模式。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。
备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉住,并外部化
存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
备忘录模式常常与命令模式和迭代子模式一同使用。
常见的软件系统往往不止存储一个状态,而是需要存储多个状态。
这些状态常常是一个对象历史发展的不同阶段的快照,存储这些快照的备忘录对象
叫做此对象的历史,某一个快照所处的位置叫做检查点。
备忘录角色:
备忘录角色有如下的责任。
1、将发起人(Originator)对象的内部状态存储起来,备忘录可以根据发起人对象的判断来决定存储多少
发起人(Originator)对象的内部状态。
2、备忘录可以保护其内容不被发起人对象之外的任何对象所读取。
备忘录有两个等效的接口:
1、窄接口:
负责人(Caretaker)对象(和其他除发起人对象之外的任何对象)看到的是备忘录的窄
接(narrowinterface),这个窄接口只允许它把备忘录对象传给其他的对象;
2、宽接口:
与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wideinterface),
这个宽接口允许它读取所有的数据,以便根据数据恢复这个发起人对象的内部状态。
853P
发起人角色:
发起人角色有如下责任:
1、创建一个含有当前的内部状态的备忘录对象。
2、使用备忘录对象存储其内部状态。
负责人角色:
负责人角色有如下的责任:
1、负责保存备忘录对象
2、不检查备忘录对象的内容。
Java代码
1.宽接口和白箱:
2. 发起人角色
3. public class Originator{
4. private String state;
5.
6. //工厂方法,返还一个新的备忘录对象
7. public Memento createMemento(){
8. return new Memento(state);
9. }
10.
11. //将发起人恢复到备忘录对象所记载的状态
12. public void restoreMemento(Memento memento){
13. this.state = memento.getState();
14. }
15.
16. //状态的取值方法
17. public String getState(){
18. return this.state;
19. }
20.
21. //状态的赋值方法
22. public void setState(String state){
23. this.state = state;
24. System.out.println("Current state = " + this.state);
25. }
26. }
27.
28. 备忘录模式要求备忘录对象提供两个不同的接口:
一个宽接口提供给发起人对象,另一个窄接口提供给所有其他的对象,包括负责人对象。
29. 宽接口允许发起人读取到所有的数据;窄接口只允许它把备忘录对象传给其他的对象而看不到内部的数据。
30. //备忘录角色
31. public class Memento{
32. private String state;
33.
34. public Memento(String state){
35. this.state = state;
36. }
37.
38. public String getState(){
39. return this.state;
40. }
41.
42. public void setState(String state){
43. this.state = state;
44. }
45. }
46.
47. 负责人角色负责保存备忘录对象,但是从不修改(甚至不查看)备忘录对象的内容(一个更好的实现是负责人对象根本无法从备忘录
48. 对象中读取个修改其内容)
49.
50. //负责人角色
51. public class Caretaker{
52. private Memento memento;
53.
54. //备忘录的取值方法
55. public Memento retrieveMemento(){
56. return this.memento;
57. }
58.
59. //备忘录的赋值方法
60. public void saveMemento(Memento memento){
61. this.memento = memento;
62. }
63. }
64.
65. //客户端
66. public class Client{
67. private static Originator o = new Originator();
68. private static Caretaker c= new Caretaker();
69. private static void main(String[] args){
70. //该负责人对象的状态
71. o.setState("On");
72. //创建备忘录对象,并将发起人对象的状态存储起来
73. c.saveMemento(o.createMemento());
74. //修改发起人对象的状态
75. o.setState("Off");
76. //恢复发起人对象的状态
77. o.restoreMemento(c.retrieveMemento());
78. }
79. }
80. 首先将发起人对象的状态设置成“On”(或者任何有效状态),并且创建一个备忘录对象将这个状态存储起来;然后将发起人对象
81. 的状态改成“Off”(或者任何状态);最后又将发起人对象恢复到备忘录对象所存储起来的状态,即“On”状态(或者先前所
82. 存储的任何状态)
83.
84. 备忘录系统运行的时序是这样的:
85.
(1)将发起人对象的状态设置成“On”。
86.
(2)调用发起人角色的createMemento()方法,创建一个备忘录对象将这个状态存储起来。
87. (3)将备忘录对象存储到负责人对象中去。
88. 备忘录系统恢复的时序是这样的:
89.
(1)将发起人对象的状态设置成“Off”;
90.
(2)将备忘录对象从负责人对象中取出;
91. (3)将发起人对象恢复到备忘录对象所存储起来的状态,“On”状态。
92.
93. 白箱实现的优缺点
94. 白箱实现的一个明显的好处是比较简单,因此常常用做教学目的。
白箱实现的一个明显的缺点是破坏对发起人状态的封装。
95.
96. 窄接口或者黑箱实现
97. //发起人角色
98. public class Originator{
99. private String state;
100.
101. public Originator(){
102. }
103.
104. //工厂方法,返还一个新的备忘录对象
105. public MementoIF createMemento(){
106. return new Memento(this.state);
107. }
108.
109. //将发起人恢复到备忘录对象记录的状态
110. public void restoreMemento(MementoIF memento){
111. Memento aMemento = (Memento)memento;
112. this.setState(aMemento.getState());
113. }
114.
115. public String getState(){
116. return this.state;
117. }
118.
119. public void setState(){
120. this.state = state;
121. System.out.println("state = " + state);
122. }
123.
124. protected class Memento implements MementoIF{
125. private String savedState;
126. private Mememto(String someState){
127. savedState = someState;
128. }
129.
130. private void setState(String someState){
131. savedState = someState;
132. }
133.
134. private String getState(){
135. return savedState;
136. }
137. }
138. }
139.
140. public interface MementoIF{}
141.
142. public class Caretaker{
143. private MementoIF memento;
144.
145. public MementoIF retrieveMemento(){
146. return this.memento;
147. }
148.
149. public void saveMemento(MementoIF memento){
150. this.memento = memento;
151. }
152. }
153.
154. public class Client{
155. private static Originator o = new Originator();
156. private static Caretaker c = new Caretaker();
157.
158. public static void main(String args[]){
159. //改变负责人对象的状态
160. o.setState("On");
161. //创建备忘录对象,并将发起人对象的状态存储起来
162. c.saveMemento(o.createMemento());
163. //修改发起人对象的状态
164. o.setState("Off");
165. //恢复发起人对象的状态
166. o.restoreMemento(c.retrieveMemento());
167. }
168. }
169.
170. 黑箱实现运行时的时序为;
171.
(1)将发起人对象的状态设置成“On”。
172.
(2)调用发起人角色的 createMemento()方法,创建一个备忘录对象将这个状态存储起来。
173. (3)将备忘录对象存储到负责人对象中去。
由于负责人对象拿到的仅是 MementoIF类型,因此无法读出备忘录内部的状态。
174. 恢复时的时序为:
175.
(1)将发起人对象的状态设置成“Off”;
176.
(2)将备忘录对象从负责人对象中取出。
注意此时仅能得到 MementoIF接口,因此无法读出此对象的内部状态
177. (3)将发起人对象的状态恢复成备忘录对象所存储起来的状态,,由于发起人对象的内部类Memento实现了MementoIF接口
178. 这个内部类是传入的备忘录对象的真实类型,因此发起人对象可以利用内部类Memento 的私有 接口读出此对象的内部状态
179.
180.存储多个状态的备忘录模式:
181. //发起人角色
182. import java.util.Vector;
183. import java.util.Enumeration;
184.
185. public class Originator{
186. private Vector states;
187. private int index;
188.
189. public Originator(){
190. states = new Vector();
191. index = 0;
192. }
193.
194. public Memento createMementor(){
195. return new Mementor(states,index);
196. }
197.
198. public void restoreMementor(Mementor memento){
199. states = memento.getStates();
200. index = memento.getIndex();
201. }
202.
203. public void setState(String state){
204. this.states.addElement(state);
205. index ++;
206. }
207.
208. //辅助方法,打印出所有的状态
209. public void printStates(){
210. System.out.println("Total number of states:
" + index);
211. for(Enumeration e = states.elements();e.hasMoreElements();){
212. system.out.println(e.nextElement());
213. }
214. }
215. }
216.
217. //备忘录角色
218. import java.util.Vector;
219.
220. public class Memento{
221. private Vector states;
222. private int index;
223.
224. public Memento(Vector states,int index){
225. this.states = (Vector)states.clone();
226. this.index = index;
227. }
228.
229. //状态取值方法
230. Vector getStates(){
231. return states;
232. }
233.
234. //检查点取值方法
235. int get