在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
名称 |
Memento |
结构 |
![](/images/cnblogs_com/darkangel/Memento.gif) |
意图 |
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 |
适用性 |
- 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。
- 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
|
Code Example |
1 // Memento 2![](/Images/OutliningIndicators/None.gif) 3 // Intent: "Without violating encapsulation, capture and externalize an 4 // object's internal state so that an object can be restored to this 5 // state later." 6![](/Images/OutliningIndicators/None.gif) 7 // For further information, read "Design Patterns", p283, Gamma et al., 8 // Addison-Wesley, ISBN:0-201-63361-2 9![](/Images/OutliningIndicators/None.gif) 10![](/Images/OutliningIndicators/ExpandedBlockStart.gif) /**//* Notes: 11 * We often have client code that wishes to record the current state of an 12 * object, without being interested in the actual data values (this is 13 * needed for undo and checkpointing). To support this behavior, we can have 14 * the object record its internal data in a helper class called a memento, and 15 * the client code can treat this as an opaque store of the object's state. 16 * At some later point, the client can pass the memento back into the object, 17 * to restore it to the previous state. 18 */ 19 20 namespace Memento_DesignPattern 21![](/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](/Images/OutliningIndicators/ContractedBlock.gif) { 22 using System; 23![](/Images/OutliningIndicators/InBlock.gif) 24 class Originator 25![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 26 private double manufacturer=0; 27 private double distributor = 0; 28 private double retailer = 0; 29![](/Images/OutliningIndicators/InBlock.gif) 30 public void MakeSale(double purchasePrice) 31![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 32 // We assume sales are divided equally amount the three 33 manufacturer += purchasePrice * .40; 34 distributor += purchasePrice *.3; 35 retailer += purchasePrice *.3; 36 // Note: to avoid rounding errors for real money handling 37 // apps, we should be using decimal integers 38 // (but hey, this is just a demo!) 39 } 40![](/Images/OutliningIndicators/InBlock.gif) 41 public Memento CreateMemento() 42![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 43 return (new Memento(manufacturer, distributor, retailer)); 44 } 45 46 public void SetMemento(Memento m) 47![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 48 manufacturer = m.A; 49 distributor = m.B; 50 retailer = m.C; 51 } 52 } 53![](/Images/OutliningIndicators/InBlock.gif) 54 class Memento 55![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 56 private double iA; 57 private double iB; 58 private double iC; 59![](/Images/OutliningIndicators/InBlock.gif) 60 public Memento(double a, double b, double c) 61![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 62 iA = a; 63 iB = b; 64 iC = c; 65 } 66![](/Images/OutliningIndicators/InBlock.gif) 67 public double A 68![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 69 get 70![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 71 return iA; 72 } 73 } 74![](/Images/OutliningIndicators/InBlock.gif) 75 public double B 76![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 77 get 78![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 79 return iB; 80 } 81 } 82![](/Images/OutliningIndicators/InBlock.gif) 83 public double C 84![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 85 get 86![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 87 return iC; 88 } 89 } 90 } 91![](/Images/OutliningIndicators/InBlock.gif) 92 class caretaker 93![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 94 95 } 96![](/Images/OutliningIndicators/InBlock.gif) 97![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//// <summary> 98 /// Summary description for Client. 99 /// </summary> 100 public class Client 101![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 102 public static int Main(string[] args) 103![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 104 Originator o = new Originator(); 105 106 // Assume that during the course of running an application 107 // we we set various data in the originator 108 o.MakeSale(45.0); 109 o.MakeSale(60.0); 110![](/Images/OutliningIndicators/InBlock.gif) 111 // Now we wish to record the state of the object 112 Memento m = o.CreateMemento(); 113![](/Images/OutliningIndicators/InBlock.gif) 114 // We make further changes to the object 115 o.MakeSale(60.0); 116 o.MakeSale(10.0); 117 o.MakeSale(320.0); 118![](/Images/OutliningIndicators/InBlock.gif) 119 // Then we decide ot change our minds, and revert to the saved state (and lose the changes since then) 120 o.SetMemento(m); 121![](/Images/OutliningIndicators/InBlock.gif) 122 return 0; 123 } 124 } 125 } 126![](/Images/OutliningIndicators/None.gif) 127![](/Images/OutliningIndicators/None.gif) |