Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

Computer Science Design Patterns/Memento

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

reading 25 22 May 2013 Add more illustrations. Mediator Model–view–controller Briefly, the Originator (the object to be saved) creates a snap-shot of itself as a Memento object, and passes that reference to the Caretaker object. The Caretaker object keeps the Memento until such a time as the Originator may want to revert to a previous state as recorded in the Memento object. Implementation in Java The following Java program illustrates the "undo" usage of the Memento Pattern. class Originator { private String state; // The class could also contain additional data that is not part of the // state saved in the memento. public void set(String state) { System.out.println("Originator: Setting state to " + state); this.state = state; } public Memento saveToMemento() { System.out.println("Originator: Saving to Memento."); return new Memento(state); } public void restoreFromMemento(Memento memento) { state = memento.getSavedState(); System.out.println("Originator: State after restoring from Memento: " + state); } public static class Memento { private final String state; private Memento(String stateToSave) { state = stateToSave; } private String getSavedState() { return state; } } } import java.util.List; import java.util.ArrayList; class Caretaker { public static void main(String[] args) { List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>(); Originator originator = new Originator(); originator.set("State1"); originator.set("State2"); savedStates.add(originator.saveToMemento()); originator.set("State3"); // We can request multiple mementos, and choose which one to roll back to. savedStates.add(originator.saveToMemento()); originator.set("State4"); originator.restoreFromMemento(savedStates.get(1)); } } The output is: Originator: Setting state to State1 Originator: Setting state to State2 Originator: Saving to Memento. Originator: Setting state to State3 Originator: Saving to Memento. Originator: Setting state to State4 Originator: State after restoring from Memento: State3 Implementation in C# ==C# Example== using System; namespace DoFactory.GangOfFour.Memento.Structural { // MainApp startup class for Structural // Memento Design Pattern. class MainApp { // Entry point into console application. static void Main() { Originator o = new Originator(); o.State = "On"; // Store internal state Caretaker c = new Caretaker(); c.Memento = o.CreateMemento(); // Continue changing originator o.State = "Off"; // Restore saved state o.SetMemento(c.Memento); // Wait for user Console.ReadKey(); } } // The 'Originator' class class Originator { private string _state; // Property public string State { get { return _state; } set { _state = value; Console.WriteLine("State = " + _state); } } // Creates memento public Memento CreateMemento() { return (new Memento(_state)); } // Restores original state public void SetMemento(Memento memento) { Console.WriteLine("Restoring state..."); State = memento.State; } } // The 'Memento' class class Memento { private readonly string _state; // Constructor public Memento(string state) { this._state = state; } // Gets or sets state public string State { get { return _state; } } } // The 'Caretaker' class class Caretaker { private Memento _memento; // Gets or sets memento public Memento Memento { set { _memento = value; } get { return _memento; } } } } ==Another way to implement memento in C#== public interface IOriginator { IMemento GetState(); } public interface IShape : IOriginator { void Draw(); void Scale(double scale); void Move(double dx, double dy); } public interface IMemento { void RestoreState(); } public class CircleOriginator : IShape { private class CircleMemento : IMemento { private readonly double x; private readonly double y; private readonly double r; private readonly CircleOriginator originator; public CircleMemento(CircleOriginator originator) { this.originator = originator; x = originator.x; y = originator.y; r = originator.r; } public void RestoreState() { originator.x = x; originator.y = y; originator.r = r; } } double x; double y; double r; public CircleOriginator(double x, double y, double r) { this.x = x; this.y = y; this.r = r; } public void Draw() { Console.WriteLine("Circle with radius {0} at ({1}, {2})", r, x, y); } public void Scale(double scale) { r *= scale; } public void Move(double dx, double dy) { x += dx; y += dy; } public IMemento GetState() { return new CircleMemento(this); } } public class RectOriginator : IShape { private class RectMemento : IMemento { private readonly double x; private readonly double y; private readonly double w; private readonly double h; private readonly RectOriginator originator; public RectMemento(RectOriginator originator) { this.originator = originator; x = originator.x; y = originator.y; w = originator.w; h = originator.h; } public void RestoreState() { originator.x = x; originator.y = y; originator.w = w; originator.h = h; } } double x; double y; double w; double h; public RectOriginator(double x, double y, double w, double h) { this.x = x; this.y = y; this.w = w; this.h = h; } public void Draw() { Console.WriteLine("Rectangle {0}x{1} at ({2}, {3})", w, h, x, y); } public void Scale(double scale) { w *= scale; h *= scale; } public void Move(double dx, double dy) { x += dx; y += dy; } public IMemento GetState() { return new RectMemento(this); } } public class Caretaker { public void Draw(IEnumerable<IShape> shapes) { foreach(IShape shape in shapes) { shape.Draw(); } } public void MoveAndScale(IEnumerable<IShape> shapes) { foreach(IShape shape in shapes) { shape.Scale(10); shape.Move(3, 2); } } public IEnumerable<IMemento> SaveStates(IEnumerable<IShape> shapes) { List<IMemento> states = new List<IMemento>(); foreach(IShape shape in shapes) { states.Add(shape.GetState()); } return states; } public void RestoreStates(IEnumerable<IMemento> states) { foreach(IMemento state in states) { state.RestoreState(); } } public static void Main() { IShape[] shapes = { new RectOriginator(10, 20, 3, 5), new CircleOriginator(5, 2, 10) }; //Outputs: // Rectangle 3x5 at (10, 20) // Circle with radius 10 at (5, 2) Draw(shapes); //Save states of figures IEnumerable<IMemento> states = SaveStates(shapes); //Change placement of figures MoveAndScale(shapes); //Outputs: // Rectangle 30x50 at (13, 22) // Circle with radius 100 at (8, 4) Draw(shapes); //Restore old placement of figures RestoreStates(states); //Outputs: // Rectangle 3x5 at (10, 20) // Circle with radius 10 at (5, 2) Draw(shapes); } } Implementation in Pascal {$apptype console} program Memento; uses SysUtils, Classes; type TMemento = class private _state: string; function GetSavedState: string; public constructor Create(stateToSave: string); property SavedState: string read GetSavedState; end; TOriginator = class private _state: string; // The class could also contain additional data that is not part of the // state saved in the memento. procedure SetState(const state: string); public function SaveToMemento: TMemento; procedure RestoreFromMemento(Memento: TMemento); property state: string read _state write SetState; end; TCaretaker = class private _memento: TMemento; public property Memento: TMemento read _memento write _memento; end; { TMemento } constructor TMemento.Create(stateToSave: string); begin _state := stateToSave; end; function TMemento.GetSavedState: string; begin writeln('restoring state from Memento'); result := _state; end; { TOriginator } procedure TOriginator.RestoreFromMemento(Memento: TMemento); begin _state := Memento.SavedState; writeln('Originator: State after restoring from Memento: ' + state); end; function TOriginator.SaveToMemento: TMemento; begin writeln('Originator: Saving to Memento.'); result := TMemento.Create(state); end; procedure TOriginator.SetState(const state: string); begin writeln('Originator: Setting state to ' + state); _state := state; end; var originator: TOriginator; c1,c2: TCaretaker; begin originator := TOriginator.Create; originator.SetState('State1'); originator.SetState('State2'); // Store internal state c1 := TCaretaker.Create(); c1.Memento := originator.SaveToMemento(); originator.SetState('State3'); // We can request multiple mementos, and choose which one to roll back to. c2 := TCaretaker.Create(); c2.Memento := originator.SaveToMemento(); originator.SetState('State4'); // Restore saved state originator.RestoreFromMemento(c1.Memento); originator.RestoreFromMemento(c2.Memento); c1.Memento.Free; c1.Free; c2.Memento.Free; c2.Free; originator.Free; end. Implementation in Scala import java.util.Date import common.patterns.Originator.Memento import scala.collection.immutable.TreeMap object Originator { case class Memento(x: Int, y: Int, time: Date) } case class Originator(var x: Int, var y: Int) { def setState(x: Int, y: Int) { this.x = x this.y = y } def createMemento(): Memento = Memento(x, y, new Date()) def restoreFromMemento(restore: Memento) { this.x = restore.x this.y = restore.y } } object Caretaker extends App { var states: TreeMap[Date, Memento] = new TreeMap val originator = new Originator(0, 0) var memento = originator.createMemento() states += (memento.time -> memento) Thread.sleep(100) originator.setState(5, 4) memento = originator.createMemento() states += (memento.time -> memento) Thread.sleep(100) originator.setState(10, 10) memento = originator.createMemento() states += (memento.time -> memento) originator.restoreFromMemento(states(states.drop(1).firstKey)) //restore second state println(originator) } Output: Originator(5,4)